generated from TREX-CoE/qmc-lttc
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpdmc.c
118 lines (90 loc) · 2.61 KB
/
pdmc.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h> // for size_t
#include <math.h>
#include <time.h>
#include "hydrogen.h"
#include "qmc_stats.h"
void pdmc(double a, size_t nmax, double dt, double *energy, double *accep,
double tau, double e_ref)
{
double chi[3], d2_old, prod, u;
double psi_old, psi_new, d2_new, argexpo, q;
double r_old[3], r_new[3];
double d_old[3], d_new[3];
size_t istep, n_accep;
double e, w, tau_current, normalization;
double sq_dt = sqrt(dt);
// Initialization
*energy = 0.0;
n_accep = 0;
normalization = 0.0;
w = 1.0;
tau_current = 0.0;
random_gauss(r_old, 3);
drift(a, r_old, d_old);
d2_old = d_old[0]*d_old[0] +
d_old[1]*d_old[1] +
d_old[2]*d_old[2];
psi_old = psi(a, r_old);
for (istep = 0; istep < nmax; istep++) {
e = e_loc(a, r_old);
w *= exp(-dt*(e-e_ref));
normalization += w;
*energy += w*e;
tau_current += dt;
// Reset when tau is reached
if (tau_current > tau) {
w = 1.0;
tau_current = 0.0;
}
random_gauss(chi, 3);
for (int i = 0; i < 3; i++) {
r_new[i] = r_old[i] + dt*d_old[i] + chi[i]*sq_dt;
}
drift(a, r_new, d_new);
d2_new = d_new[0]*d_new[0] +
d_new[1]*d_new[1] +
d_new[2]*d_new[2];
psi_new = psi(a, r_new);
// Metropolis
prod = (d_new[0] + d_old[0])*(r_new[0] - r_old[0]) +
(d_new[1] + d_old[1])*(r_new[1] - r_old[1]) +
(d_new[2] + d_old[2])*(r_new[2] - r_old[2]);
argexpo = 0.5 * (d2_new - d2_old)*dt + prod;
q = psi_new / psi_old;
q = exp(-argexpo) * q*q;
u = drand48();
if (u <= q) {
n_accep++;
for (int i = 0; i < 3; i++) {
r_old[i] = r_new[i];
d_old[i] = d_new[i];
}
d2_old = d2_new;
psi_old = psi_new;
}
}
*energy = *energy / normalization;
*accep = (double) n_accep / (double) nmax;
}
int main(void) {
#define a 1.2
#define dt 0.05
#define e_ref -0.5
#define tau 100.0
#define nmax 100000
#define nruns 30
double X[nruns];
double Y[nruns];
double ave, err;
srand48(time(NULL));
for (size_t irun = 0; irun < nruns; irun++) {
pdmc(a, nmax, dt, &X[irun], &Y[irun], tau, e_ref);
}
ave_error(X, nruns, &ave, &err);
printf("E = %f +/- %f\n", ave, err);
ave_error(Y, nruns, &ave, &err);
printf("A = %f +/- %f\n", ave, err);
return 0;
}