// PROGRAM qmwalk #include "TrueBASIC.h" int main(); void initial(double x[], int *N, int *N0, double *Vref, double *binsize, double *ds, double *dt, int *mcs, int *nequil, double *Esum); void walk(double x[], int *N, int N0, double *Vref, double *Vave, double ds, double dt); void data(double x[], double psi[], int N, double Vref, double Vave, double *Esum, int imcs, double binsize); void plot_psi(double psi[], double binsize); double V(double x); int main() { int N, N0, i, imcs, mcs, nequil; double Esum, Vave, Vref, binsize, ds, dt, psi[1001], x[2001]; for(i = 0; i <= 1000; ++i) { psi[i] = 0; } for(i = 0; i <= 2000; ++i) { x[i] = 0; } GWopen(0); initial(x, &N, &N0, &Vref, &binsize, &ds, &dt, &mcs, &nequil, &Esum); for(i = 1; i <= nequil; ++i) // equilibration walk(x, &N, N0, &Vref, &Vave, ds, dt); for(imcs = 1; imcs <= mcs; ++imcs) { walk(x, &N, N0, &Vref, &Vave, ds, dt); data(x, psi, N, Vref, Vave, &Esum, imcs, binsize); } plot_psi(psi, binsize); GWquit(); return 0; } void initial(double x[], int *N, int *N0, double *Vref, double *binsize, double *ds, double *dt, int *mcs, int *nequil, double *Esum) { int i; double width; char Stmp1_[_LBUFF_]; rnd(-1); printf("desired number of walkers = "); fgets(Stmp1_, _LBUFF_, stdin); sscanf(Stmp1_, "%d", N0); printf("step length = "); fgets(Stmp1_, _LBUFF_, stdin); sscanf(Stmp1_, "%lg", ds); (*dt) = (*ds)*(*ds); // time step printf("number of Monte Carlo steps per walker = "); fgets(Stmp1_, _LBUFF_, stdin); sscanf(Stmp1_, "%d", mcs); (*nequil) = (int)(0.4*(*mcs)); // choose initial number of walkers equal to desired number (*N) = (*N0); // choose initial positions of walkers at random width = 1; // initial width of region for walkers (*Vref) = 0; for(i = 1; i <= (*N); ++i) { x[i] = (2*rnd(0) - 1)*width; (*Vref) += V(x[i]); } (*Vref) /= (*N); (*binsize) = 2*(*ds); // binsize for psi array (*Esum) = 0; GWclear(-1); printf(" MC steps N E Vref\n"); printf("\n"); } void walk(double x[], int *N, int N0, double *Vref, double *Vave, double ds, double dt) { int Nin, i; double Vsum, dV, potential; Nin = (*N); // # walkers at beginning of trial Vsum = 0; for(i = Nin; i >= 1; --i) { if(rnd(0) < 0.5) x[i] += ds; else x[i] -= ds; potential = V(x[i]); // potential at x dV = potential - (*Vref); if(dV < 0) // check to add walker { if(rnd(0) < -dV*dt) { ++(*N); x[(*N)] = x[i]; // new walker // factor of 2 since two walkers at x Vsum += 2*potential; } else Vsum += potential; // only do old walker } else { if(rnd(0) < dV*dt) // check to remove walker { x[i] = x[(*N)]; --(*N); } else Vsum += potential; } } (*Vave) = Vsum/(*N); // mean potential (*Vref) = (*Vave) - ((*N) - N0)/(N0*dt); // new reference energy } void data(double x[], double psi[], int N, double Vref, double Vave, double *Esum, int imcs, double binsize) { int bin, i; // accumulate data (*Esum) += Vave; // bin walkers for(i = 1; i <= N; ++i) { bin = (int)(x[i]/binsize); ++(psi[bin + 500]); } if(((imcs) % (10)) == 0) { printf("%12d ", imcs); printf("%12d ", N); printf("%12.3f ", (*Esum)/imcs); printf("%12.3f\n", Vref); } } void plot_psi(double psi[], double binsize) { int i, imax; double P, norm, pmax, sum = 0, ymax; i = 0; pmax = psi[i + 500]*psi[i + 500]; sum = pmax; do { ++i; P = psi[i + 500]*psi[i + 500] + psi[-i + 500]*psi[-i + 500]; if(P > pmax) pmax = P; sum += P; } while(!(P == 0)); imax = i; norm = sqrt(sum*binsize); ymax = sqrt(pmax)/norm; GWindow((float)(-imax), (float)(-0.1*ymax), (float)(imax), (float)(1.1*ymax)); GWline((float)(-imax), 0.0f, (float)(imax), 0.0f); for(i = -imax; i <= imax; ++i) GWline((float)(i-1), (float)(psi[i + 499]/norm), (float)(i), (float)(psi[i + 500]/norm)); } double V(double x) { double V_; V_ = 0.5*x*x; return V_; }