The Monte Carlo Algorithm This algorithm was invented by N. Metropolis, A.W. Rosenbluth, M.N. Rosenbluth, A.H. Teller, and E. Teller, J. Chem. Phys., 21, 1087 (1953). It was listed as one of the The Top 10 Algorithms of the 20th Century in a recent issue of Computing in Science and Engineering. Suppose we wish to generate random numbers distributed according to a positive definite function in one dimension, for example P (x) = e x2 /2. The function need not be normalized for the algorithm to work, and the same algorithm works just as easily in a many dimensional space. The random number sequence x i, i = 0, 1, 2,... is generated by a random walk as follows: Choose a starting point x 0. Choose a fixed maximum step size δ. Given an x i, generate the next random number as follows: Choose x trial uniformly and randomly in the interval [x i δ, x i + δ]. Compute the ratio w = P (x trial). P (x i ) Note that P need not be normalized to compute this ratio. PHY 411-506 Computational Physics 2 1 Wednesday, February 12
If w > 1 the trial step is in the right direction, i.e., towards a region of higher probability. Accept the step x i+1 = x trial. If w < 1 the trial step is in the wrong direction, i.e., towards a region of lower probability. We should not unconditionally reject this step! (Why?) So accept the step conditionally if the decrease in probability is smaller than a random amount: Generate a random number r in the interval [0, 1]. If r < w accept the trial step x i+1 = x trial. If w r reject the step x i+1 = x i. Note that we don t discard this step! The two steps have the same value. This algorithm is implemented in the following program metropolis.cpp to compute the same Gaussian integral as previously. # estimate Gaussian integral using the Monte Carlo algorithm metropolis.py from math import exp, pi, sqrt from random import random def P(x): return exp(- x**2 / 2) / sqrt(2 * pi) PHY 411-506 Computational Physics 2 2 Wednesday, February 12
def f_over_w(x): return x**2 x = 0.0 delta = 1.0 accepts = 0 # initial position of walker # step size # number of steps accepted def MetropolisStep(): global x, accepts # updated the global value xtrial = x + (2 * random() - 1) * delta w = P(xTrial) / P(x) if w >= 1: # uphill x = xtrial # accept the step accepts += 1 else: # downhill if random() < w: # but not too far x = xtrial # accept the step accepts += 1 # get input parameters from user delta = float(input(" Enter step size delta: ")) PHY 411-506 Computational Physics 2 3 Wednesday, February 12
M = int(input(" Enter number of trials: ")) N = int(input(" Enter steps per trial: ")) fsum = 0.0 sqdsum = 0.0 errsum = 0.0 for i in range(m): avg = 0.0 var = 0.0 for j in range(n): MetropolisStep() fx = f_over_w(x) avg += fx var += fx**2 avg /= N var /= N var = var - avg**2 err = sqrt(var / N) fsum += avg sqdsum += avg**2 errsum += err ans = fsum / M # accumulator for <f> # accumulator for <f> * <f> # accumulator error estimates # accumulator for f(x) # accumulator for f(x) * f(x) PHY 411-506 Computational Physics 2 4 Wednesday, February 12
stddev = sqrt(sqdsum / M - ans**2) stddev /= sqrt(float(m)) err = errsum / M err /= sqrt(float(m)) print("\n Exact answer: " + str(1.0)) print(" Integral: " + str(ans) + " +- " + str(err)) print(" Std. Dev.: " + str(stddev)) print(" Accept ratio: " + str(accepts / float(n * M))) // estimate Gaussian integral using the Monte Carlo algorithm metropolis.cpp #include <cmath> #include <cstdlib> #include <iostream> using namespace std; const double pi = 4 * atan(1.0); inline double std_rand() { PHY 411-506 Computational Physics 2 5 Wednesday, February 12
return rand() / (RAND_MAX + 1.0); double P(double x) { return exp(- x * x / 2) / sqrt(2 * pi); double f_over_w(double x) { return x * x; double x = 0; double delta = 1.0; int accepts = 0; // initial position of walker // step size // number of steps accepted void MetropolisStep() { double xtrial = x + (2 * std_rand() - 1) * delta; double w = P(xTrial) / P(x); if (w >= 1) { // uphill x = xtrial; // accept the step ++accepts; PHY 411-506 Computational Physics 2 6 Wednesday, February 12
else { // downhill if (std_rand() < w) { // but not too far x = xtrial; // accept the step ++accepts; int main() { // get input parameters from user cout << "Enter step size delta: "; cin >> delta; cout << "Enter number of trials: "; int M; cin >> M; cout << "Enter steps per trial: "; int N; cin >> N; double sum = 0; double sqdsum = 0; // accumulator for <f> // accumulator for <f> * <f> PHY 411-506 Computational Physics 2 7 Wednesday, February 12
double errsum = 0; // accumulator error estimates for (int i = 0; i < M; i++) { double avg = 0; // accumulator for f(x) double var = 0; // accumulator for f(x) * f(x) for (int j = 0; j < N; j++) { MetropolisStep(); double fx = f_over_w(x); avg += fx; var += fx * fx; avg /= N; var /= N; var = var - avg * avg; double err = sqrt(var / N); sum += avg; sqdsum += avg * avg; errsum += err; double ans = sum / M; double stddev = sqrt(sqdsum / M - ans * ans); stddev /= sqrt(double(m)); double err = errsum / M; PHY 411-506 Computational Physics 2 8 Wednesday, February 12
err /= sqrt(double(m)); cout << "\n Exact answer: " << 1.0 << endl; cout << " Integral: " << ans << " +- " << err << endl; cout << " Std. Dev.: " << stddev << endl; cout << " Accept ratio: " << accepts / double(n * M) << endl; There are essentially two important choices to be made: The initial point x 0 must be chosen carefully. A good choice is close to the maximum of the desired probability distribution. If this maximum is not known (as is usually the case in multi dimensional problems), then the random walker must be allowed to thermalize i.e., to find a good starting configuration: the algorithm is run for some large number of steps which are then discarded. The step size δ must be carefully chosen. If δ is too small, then most of the trial steps will be accepted, which will tend to give a uniform distribution that converges very slowly to P (x). If δ is too large the random walker will step right over and not see important peaks in the probability distribution. If the walker is at a peak, too many steps will be rejected. PHY 411-506 Computational Physics 2 9 Wednesday, February 12
A rough criterion for choosing the step size is for the to be around 0.5. Acceptance ratio = Number of steps accepted Total number of trial steps Hard Disk Gas: Equation of State Calculations by Fast Computing Machine The classic article by N. Metropolis, A.W. Rosenbluth, M.N. Rosenbluth, A.H. Teller, J. Chem. Phys. 21, 1087 (1953), was the first computer simulation of a physical system. Along with the Fermi-Pasta-Ulam Report, it marked the beginning of computational science as a third way of studying the physical world in addition to experiment and theory. Maxwell Boltzmann Kinetic Theory The system of hard disks was treated as a Maxwell-Boltzmann gas at fixed volume and temperature. The energy of gas of disks is given by E = K.E. + P.E. = m 2 v 2 i + U(r ij ), i pairs ij PHY 411-506 Computational Physics 2 10 Wednesday, February 12
with a pairwise potential energy function where σ is the disk diameter. U(r) = { 0 if r > σ if r σ, Thermal Equilibrium Consider an ensemble of systems. At absolute temperature T the probability that a system has energy E is given by the Boltzmann distribution [ W exp E ] [ = exp E T S ] [ = exp F ], k B T k B T k B T where W is the number of microscopic configurations with energy E, k B is Boltzmann s constant, S = k B log W is the entropy, and F = E T S is the free energy. The partition function is given by Z = E W (E) exp [ E ] k B T. The equation of state of the gas relates pressure p, volume V, and absolute temperature T pv = Nk B T log Z log V. T,N PHY 411-506 Computational Physics 2 11 Wednesday, February 12
Monte Carlo Simulation of Hard Disks Metropolis et al. designed a volume to close-pack N = 224 disks of diameter d 0 as shown in the figures below from their article. PHY 411-506 Computational Physics 2 12 Wednesday, February 12
The placed 14 particles per row 16 per column on a triangular lattice. They chose to fix A 0 = 3d 2 0N/2 = 1 and vary d 0, hence the number of disks N. Periodic boundary conditions were used to approximate an infinite volume and avoid having to apply boundary conditions at the walls of the container. Radial distribution histogram The Radial distribution function measures the correlations between particles separated a distances r. PHY 411-506 Computational Physics 2 13 Wednesday, February 12
It can be measured experimentally and in computer simulations. It can be used to distinguish the solid, liquid and gaseous states. The equation of state p(n, V, T ) was deduced from the radial distribution function n(r) shown in the figures below. PHY 411-506 Computational Physics 2 14 Wednesday, February 12
They showed that P A = Nk B T using the Virial Theorem of Clausius. ( ) 1 + πd2 0n 2, where n = n(d), The Virial theorem states K.E. = N 1 2 mv2 = pa + 1 2 i r i X int i The derivation is based on the figure below, which defines the variables involved in a collision between two disks.. PHY 411-506 Computational Physics 2 15 Wednesday, February 12
The result of this derivation is r i X int i i = 1 2 r ij F ij = N 1 2 mv2 πd 2 0n. i j i The Monte Carlo simulation measured the radial distribution function as a histogram: For each Monte Carlo configuration Consider any disk Divide the region from r = d to r = r max into 64 annular zones of equal area Count number of disks in each zone and store in histogram with 64 bins Repeat for all other disks and accumulate in histogram Average over configurations Fit histogram to a model function and extrapolate to r = d PHY 411-506 Computational Physics 2 16 Wednesday, February 12