/************************* Program 9.2 ****************************/ /* */ /************************************************************************/ /* Please Note: */ /* */ /* (1) This computer program is written by Tao Pang in conjunction with */ /* his book, "An Introduction to Computational Physics," published */ /* by Cambridge University Press in 1997. */ /* */ /* (2) No warranties, express or implied, are made for this program. */ /* */ /************************************************************************/ #include #include #include #define NMAX 10000 #define MMAX 10000 #define LMAX 15 #define g(x) (x*x/(exp(x*x)-1)) #define w(x) (exp(x*x)-1) int iseed,icpt; double x,b,wt; void mtsp(void); main() /* Integral evaluated with the Metropolis Monte Carlo scheme. w(x) is the distribution function and g(x) is the function to be sampled. Copyright (c) Tao Pang 1997. */ { int i,n,m,l; int t1,t2,t3,t4,t5,t6; time_t ts,tp; struct tm t; double z,sum1,sum2,st,ds,at; double ranf(); extern int iseed,icpt; extern double x,b,wt; n = NMAX; m = MMAX; l = LMAX; b = 0.4; z = 0.46265167; /* Initial seed from the system time and and forced to be odd */ ts = time(&tp); t = *gmtime(&tp); t1 = t.tm_sec; t2 = t.tm_min; t3 = t.tm_hour; t4 = t.tm_mday; t5 = t.tm_mon; t6 = t.tm_year; iseed = t6+70*(t5+12*(t4+31*(t3+23*(t2+59*t1)))); if ((iseed%2) == 0) { iseed = iseed-1; } /* Remove the initial configuration dependence */ x = ranf(); wt = w(x); for (i = 0; i < m; ++i) { mtsp(); } /* Collect data at every nf steps */ sum1 = 0; sum2 = 0; icpt = 0; for (i = 0; i < n*l; ++i) { mtsp(); if (i%l == 0) { sum1 = sum1+g(x); sum2 = sum2+g(x)*g(x); } } st = z*sum1/n; ds = z*sqrt(fabs(sum2/n-(sum1/n)*(sum1/n))/n); at = 100.0*icpt/(n*l); printf("%16.8lf %16.8lf %16.8lf\n", st,ds,at); } void mtsp(void) /* Subroutine for one Metropolis step. Copyright (c) Tao Pang 1997. */ { double xsav,rndx,wtry,rndw; double ranf(); extern int iseed,icpt; extern double x,b,wt; xsav = x; rndx = ranf(); x = x+2*b*(rndx-0.5); if ((x < 0) || (x > 1)) { x = xsav; } else { wtry = w(x); rndw = ranf(); if (wtry > (wt*rndw)) { wt = wtry; icpt = icpt+1; } else { x = xsav; } } } double ranf() /* Uniform random number generator x(n+1)= a*x(n) mod c with a = pow(7,5) and c = pow(2,31)-1. Copyright (c) Tao Pang 1997. */ { const int ia=16807,ic=2147483647,iq=127773,ir=2836; int il,ih,it; double rc; extern int iseed; ih = iseed/iq; il = iseed%iq; it = ia*il-ir*ih; if (it > 0) { iseed = it; } else { iseed = ic+it; } rc = ic; return iseed/rc; }