MC Simulation Lab 7: 2-Dimensional Lennard-Jones Simple Liquid (Off-Lattice) and Its Phase Transition.

Slides:



Advertisements
Similar presentations
PRAGMA – 9 V.S.S.Sastry School of Physics University of Hyderabad 22 nd October, 2005.
Advertisements

Simulazione di Biomolecole: metodi e applicazioni giorgio colombo
How to setup the initial conditions for a Molecular Dynamic Simulation
Review Of Statistical Mechanics
Molecular Dynamics at Constant Temperature and Pressure Section 6.7 in M.M.
Lecture 13: Conformational Sampling: MC and MD Dr. Ronald M. Levy Contributions from Mike Andrec and Daniel Weinstock Statistical Thermodynamics.
Monte Carlo Methods and Statistical Physics
Ch 11. Sampling Models Pattern Recognition and Machine Learning, C. M. Bishop, Summarized by I.-H. Lee Biointelligence Laboratory, Seoul National.
1 CE 530 Molecular Simulation Lecture 8 Markov Processes David A. Kofke Department of Chemical Engineering SUNY Buffalo
MAE 552 – Heuristic Optimization Lecture 6 February 6, 2002.
TMS Feb 2010 ZMC: A Tool for Modelling Diffuse Scattering from Single Crystals D.J.Goossens AINSE Fellow Research School of Chemistry Australian National.
CE 400 Honors Seminar Molecular Simulation Prof. Kofke Department of Chemical Engineering University at Buffalo, State University of New York Class 4.
1 CE 530 Molecular Simulation Lecture 2 David A. Kofke Department of Chemical Engineering SUNY Buffalo
Joo Chul Yoon with Prof. Scott T. Dunham Electrical Engineering University of Washington Molecular Dynamics Simulations.
1 CE 530 Molecular Simulation Lecture 3 David A. Kofke Department of Chemical Engineering SUNY Buffalo
Monte Carlo Methods H. Rieger, Saarland University, Saarbrücken, Germany Summerschool on Computational Statistical Physics, NCCU Taipei, Taiwan.
Introduction to Monte Carlo Methods D.J.C. Mackay.
Monte Carlo Simulation of Ising Model and Phase Transition Studies By Gelman Evgenii.
1 CE 530 Molecular Simulation Lecture 7 David A. Kofke Department of Chemical Engineering SUNY Buffalo
Advanced methods of molecular dynamics Monte Carlo methods
1 Statistical Mechanics and Multi- Scale Simulation Methods ChBE Prof. C. Heath Turner Lecture 11 Some materials adapted from Prof. Keith E. Gubbins:
Monte-Carlo simulations of the structure of complex liquids with various interaction potentials Alja ž Godec Advisers: prof. dr. Janko Jamnik and doc.
Introduction and Vectors
1 Scalar Properties, Static Correlations and Order Parameters What do we get out of a simulation? Static properties: pressure, specific heat, etc. Density.
Free energies and phase transitions. Condition for phase coexistence in a one-component system:
TUTORIAL no. 2 Monte Carlo simulations: Lennard Jones gas G. Lattanzi Università degli studi di Bari “Aldo Moro” Trieste, July 10 th, 2012 CECAM school.
Monte Carlo Simulation: Simulate an Isothermal-Isobaric Ensemble Timothy Tie Dong Bing School of Physics, Computer Lab 25 th Jan 2013.
Molecular Dynamics Simulation Solid-Liquid Phase Diagram of Argon ZCE 111 Computational Physics Semester Project by Gan Sik Hong (105513) Hwang Hsien Shiung.
1 CE 530 Molecular Simulation Lecture 17 Beyond Atoms: Simulating Molecules David A. Kofke Department of Chemical Engineering SUNY Buffalo
1 CE 530 Molecular Simulation Lecture 18 Free-energy calculations David A. Kofke Department of Chemical Engineering SUNY Buffalo
Basic Monte Carlo (chapter 3) Algorithm Detailed Balance Other points.
Basics of molecular dynamics. Equations of motion for MD simulations The classical MD simulations boil down to numerically integrating Newton’s equations.
Microscopic states (microstates) or microscopic configurations under external constraints (N or , V or P, T or E, etc.)  Ensemble (micro-canonical, canonical,
1 CE 530 Molecular Simulation Lecture 6 David A. Kofke Department of Chemical Engineering SUNY Buffalo
Ionic Conductors: Characterisation of Defect Structure Lecture 15 Total scattering analysis Dr. I. Abrahams Queen Mary University of London Lectures co-financed.
Simulated Annealing.
For a new configuration of the same volume V and number of molecules N, displace a randomly selected atom to a point chosen with uniform probability inside.
1 Statistical Mechanics and Multi- Scale Simulation Methods ChBE Prof. C. Heath Turner Lecture 14 Some materials adapted from Prof. Keith E. Gubbins:
8. Selected Applications. Applications of Monte Carlo Method Structural and thermodynamic properties of matter [gas, liquid, solid, polymers, (bio)-macro-
Monte Carlo Methods So far we have discussed Monte Carlo methods based on a uniform distribution of random numbers on the interval [0,1] p(x) = 1 0  x.
1 CE 530 Molecular Simulation Lecture 22 Chain-Molecule Sampling Techniques David A. Kofke Department of Chemical Engineering SUNY Buffalo
Plan Last lab will be handed out on 11/22. No more labs/home works after Thanksgiving. 11/29 lab session will be changed to lecture. In-class final (1hour):
1 M.Sc. Project of Hanif Bayat Movahed The Phase Transitions of Semiflexible Hard Sphere Chain Liquids Supervisor: Prof. Don Sullivan.
Importance sampling for MC simulation
Simulated Annealing G.Anuradha.
Molecular Modelling - Lecture 2 Techniques for Conformational Sampling Uses CHARMM force field Written in C++
ChE 452 Lecture 17 Review Of Statistical Mechanics 1.
Chapter 9: Molecular-dynamics Integrate equations of motion-- classical! Discrete form of Newton’s second law Forces from interaction potential For a simple.
Path Integral Quantum Monte Carlo Consider a harmonic oscillator potential a classical particle moves back and forth periodically in such a potential x(t)=
Monte Carlo method: Basic ideas. deterministic vs. stochastic In deterministic models, the output of the model is fully determined by the parameter values.
Interacting Molecules in a Dense Fluid
An Introduction to Monte Carlo Methods in Statistical Physics Kristen A. Fichthorn The Pennsylvania State University University Park, PA
 2008 Pearson Education, Inc. All rights reserved. 1 Arrays and Vectors.
Monte Carlo methods (II) Simulating different ensembles
Javier Junquera Importance sampling Monte Carlo. Cambridge University Press, Cambridge, 2002 ISBN Bibliography.
MSc in High Performance Computing Computational Chemistry Module Parallel Molecular Dynamics (i) Bill Smith CCLRC Daresbury Laboratory
1 Molecular Simulations Macroscopic EOS (vdW, PR) Little molecular detail Empirical parameters (  ) Seeking understanding of complex systems Surfactants.
Statistical Mechanics and Multi-Scale Simulation Methods ChBE
Can we use Monte Carlo to compute Z? (even for a very simple, minimum-size, discrete case) Consider a model of spins on a 2D lattice (idealized magnetic.
Computational Physics (Lecture 4) PHY4370. Random Variable, density function and distribution function.
Computational Physics (Lecture 10) PHY4370. Simulation Details To simulate Ising models First step is to choose a lattice. For example, we can us SC,
Pattern Formation via BLAG Mike Parks & Saad Khairallah.
Monte Carlo Simulation of the Ising Model Consider a system of N classical spins which can be either up or down. The total.
Systematic errors of MC simulations Equilibrium error averages taken before the system has reached equilibrium  Monitor the variables you are interested.
Computational Physics (Lecture 10)
Overview of Molecular Dynamics Simulation Theory
Scalar Properties, Static Correlations and Order Parameters
Common Types of Simulations
CE 530 Molecular Simulation
Presentation transcript:

MC Simulation Lab 7: 2-Dimensional Lennard-Jones Simple Liquid (Off-Lattice) and Its Phase Transition

Lennard-Jones (vdW) interaction potential V(r)

Almost always involves a Markov process Move to a new configuration from an existing one according to a well-defined transition probability Simulation procedure 1.Generate a new “trial” configuration by making a perturbation to the present configuration 2.Accept the new configuration based on the ratio of the probabilities for the new and old configurations, according to the Metropolis algorithm 3.If the trial is rejected, the present configuration is taken as the next one in the Markov chain 4.Repeat this many times, accumulating sums for averages state k state k+1 David A. Kofke, SUNY Buffalo 2-Dimensional Lennard-Jones Simple Liquid (Off-Lattice)

Simulation box = square (2D) or cubic (3D) Number of particles N = 30 x 30 = 900 Density ρ = 0.8 particles/σ 2 Size of the box L = (N/ρ) 1/2 Cutoff radius r C = L/2 Temperature T = Make a suitable test to check for periodic boundary conditions. 2.Make sure that your acceptance rate is between 30 and 50%. 3.Equilibrate the system: Calculate the total energy U for each configuration, its average and the correlation function. 4.Obtain for different temperatures and the specific heat. 5.Check your result with the specific heat evaluated from the fluctuation analysis: mc ndim init nx ny density temp rcutoff nsteps nopt displmax seed graphswitch mc versus

/* Get command-line input */ if (argc != 13) { fprintf(stderr, "Usage: %s n_dim init n_x n_y density temp r_cutoff n_steps n_opt displ_max seed graph_switch\n", argv[0]); exit(1); } n_dim = atoi(argv[1]); init = atoi(argv[2]); n_x = atoi(argv[3]); n_y = atoi(argv[4]); density = atof(argv[5]); temp = atof(argv[6]); r_cutoff = atof(argv[7]); n_steps = atoi(argv[8]); n_opt = atoi(argv[9]); displ_max = atof(argv[10]); seed = atoi(argv[11]); graph_switch = atoi(argv[12]); sigma = 1.0; epsilon = 1.0; mc.c (part 1) mc ndim init nx ny density temp rcutoff nsteps nopt displmax seed graphswitch mc

/* Derived parameters. */ n_atoms = n_x * n_y; /* LJ parameters */ sigma2 = SQR(sigma); four_epsilon = 4.0 * epsilon; /* range of interactions. */ r_cutoff2 = SQR(r_cutoff); if (init == 1 && n_dim != 2 ) { printf("crystal builder only for n_dim = 2\n"); exit(1); } if (init == 1 && n_y % 2 !=0) { printf("n_y must be even for crystal builder\n"); exit(1); } if (init == 1 && density > 2.0 / sqrt(3.0) / sigma2) { printf("density must be lower or equal to %g\n", 2.0 / sqrt(3.0) / sigma2); exit(1); } mc.c (part 2)

Reduced units Unit of length = σ (i.e.  = 1) Unit of energy = ε (i.e.  = 1) Unit of mass = m (i.e. m = 1) All the other units descend from these. Unit of time = Unit of temperature =  / k B  LJ vdW interaction potential in these unit:

Lennard-Jones (vdW) interaction potential V(r)

/* Allocate memory. */ h = (double*) allocate_1d_array(n_dim, sizeof(double)); h_inv = (double*) allocate_1d_array(n_dim, sizeof(double)); r = (double**) allocate_2d_array(n_atoms, n_dim, sizeof(double)); s = (double**) allocate_2d_array(n_atoms, n_dim, sizeof(double)); if (init == 0) { /* build isotropic */ /* Create simple unit cell with specified number density. */ for (i = 0; i < n_dim; ++i) { h[i] = pow(n_atoms / density, 1.0 / n_dim); h_inv[i] = 1.0 / h[i]; } /* Build an isotropic initial configuration. */ build_isotropic(n_dim, n_atoms, sigma2, r, s, h, &seed); } else { /* build crystal 2d */ /* Create simple unit cell with specified number density. */ a = sqrt(2.0 / sqrt(3.0) / density); h[0] = n_x * a; h_inv[0] = 1.0 / h[0]; h[1] = n_y * sqrt(3.0) * 0.5 * a; h_inv[1] = 1.0 / h[1]; /* Build a hexagonal crystal initial configuration. */ build_crystal(n_dim, n_x, n_y, a, r, s, h); } mc.c (part 3)

#include "test.h" #include "build_crystal.h" void build_crystal(int n_dim, int n_x, int n_y, double a, double **r, double **s, double *h) { int i, j, k; k = 0; /* Loop over atoms. */ for (j = 0; j < n_y / 2; ++j) { for (i = 0; i < n_x; ++i) { /* Generate scaled and real atom position (2 atoms per unit cell). */ r[k][0] = -n_x * i * a; r[k][1] = -n_y * j * a * sqrt(3.0); s[k][0] = r[k][0] / h[0]; s[k][1] = r[k][1] / h[1]; ++k; r[k][0] = r[k-1][0] + a * 0.5; r[k][1] = r[k-1][1] + sqrt(3) * a * 0.5; s[k][0] = r[k][0] / h[0]; s[k][1] = r[k][1] / h[1]; ++k; } printf("\nConfiguration building completed\n"); fflush(NULL); return; /* Return zero if the initial condition is successfully constructed. */ } build_crystal.c

#include "test.h" #include "build_isotropic.h" #include "ran3.h" #define MAX_TRIALS void build_isotropic(int n_dim, int n_atoms, double sigma2, double **r, double **s, double *h, long *seed) { int i, i_atom, j_atom, n_trials, overlap_flag; double r2; static int first_call = 1; static double *s_pair, *r_pair; if (first_call) { s_pair = (double*) allocate_1d_array(n_dim, sizeof(double)); r_pair = (double*) allocate_1d_array(n_dim, sizeof(double)); first_call = 0; } /* Loop over atoms. */ for (i_atom = 0; i_atom < n_atoms; ++i_atom) { /* Generate trial position for atom i until an overlap-free set is found. */ n_trials = 0; do { build_isotropic.c (part 1)

/* Exit with nonzero return value if maximum number of trial insertions is exceeded. */ if (n_trials > MAX_TRIALS) { printf("Maximum number of trials exceeded in amorphous builder\n"); exit(1); } /* Generate scaled and real trial atom position. */ for (i = 0; i < n_dim; ++i) { s[i_atom][i] = ran3(seed) - 0.5; r[i_atom][i] = s[i_atom][i] * h[i]; } /* Check for overlaps between i_atom and the atoms already in the unit cell. */ overlap_flag = 0; for (j_atom = 0; j_atom < i_atom; ++j_atom) { r2 = 0.0; /* Compute distance between atoms i_atom and j_atom */ for (i = 0; i < n_dim; ++i) { s_pair[i] = s[j_atom][i] - s[i_atom][i]; s_pair[i] -= NINT(s_pair[i]); r_pair[i] = s_pair[i] * h[i]; r2 += SQR(r_pair[i]); } build_isotropic.c (part 2)

/* Exit if an overlap is found. */ if (r2 < sigma2) { overlap_flag = 1; break; } /* Increment trial counter. */ ++n_trials; } while (overlap_flag); /* Print out number of trials required for successful particle insertion. */ printf("i_atom = %d, n_trials = %d\n", i_atom, n_trials); fflush(NULL); } /* next atom. */ printf("\nConfiguration building completed\n"); fflush(NULL); return; /* Return zero if the initial condition is successfully constructed. */ } #undef MAX_TRIALS build_isotropic.c (part 3)

Initial configuration: Usually, start from a lattice. Historically, the FCC structure has been the starting configuration (for 3D). The lattice spacing is chosen so the appropriate liquid state density is obtained. During the course of the simulation, the lattice structure will disappear, to be replaced by a typical liquid structure. This process of “melting” can be enhanced by giving each molecule a small random displacement from its initial lattice point. A supercell is constructed repeating the conventional cubic unit cell of the FCC lattice N times along each direction. For 2D? We may choose to place the N particles randomly or on a cubic lattice. We are interested in equilibrium properties, hence our results MUST not depend on the initial configuration. If they do, our simulation is simply WRONG. Almost any lattice is suitable.

Units of the mass, density, and lattice constant For systems consisting of just one type of atom or molecule, it is sensible to use the mass of the molecule as a fundamental unit. m = 1 (dimensionless) With this convention: -Particle momenta and velocities become numerically identical (in MD). -Forces and accelerations become numerically identical (in MD). Lattice constant of a closely-packed FCC lattice (4 atoms in a cubic unit cell), Density of systems interacting via LJ potential  * =  3 (3D) or  2 (2D) Lattice constant of a closely-packed 2D lattice? Scaled unit: Lattice constant L = 1, atomic coordinates in [-0.5, 0.5]

/* Initialize graphics. */ antialias_switch = 1; radius = sigma / 2.0; resph = 8; if (graph_switch > 0 && n_dim == 2) { initialize_2d(&dpy, &win, doubleBuffer, &qobj, graph_switch, antialias_switch, h); // while (1) redraw_2d(dpy, win, doubleBuffer, qobj, n_atoms, r, h, radius, resph); } if (graph_switch > 0 && n_dim == 3) { initialize_3d(&dpy, &win, doubleBuffer, &qobj, graph_switch, antialias_switch, h); redraw_3d(dpy, win, doubleBuffer, qobj, n_atoms, r, h, radius, resph); } /* Compute initial potential energy */ pot_energy = compute_pot(n_dim, n_atoms, s, h, sigma2, four_epsilon, r_cutoff2); /* Print energy. */ fprintf(stderr, "\n\nInitial\n"); fprintf(stderr, "\n\nPotential energy = %12.8f\n", pot_energy); mc.c (part 4)

/* Initialize variables for MC optimization. */ n_trial = 0; n_accept = 0; sum_displ2 = 0; cpu_time = 0; displ_max_old = displ_max; displ_efficiency = 0; displ_cutoff = r_cutoff; /* Open thermodynamic file. */ fp = fopen("thermo.out", "a"); /* MC loop. */ for (i_step = 1; i_step <= n_steps; ++i_step) { /* Perform a MC cycle. */ mc_cycle(n_dim, n_atoms, r, s, displ_max, h, h_inv, temp, sigma2, four_epsilon, r_cutoff2, &seed, &pot_energy, &sum_displ2, &n_trial, &n_accept); /* Write thermodynamic quantities in file every cycle. */ fprintf(fp, "%d %12.8f\n", i_step, pot_energy); mc.c (part 5)

/* Optimize displ_max every n_opt_steps. */ if ((n_opt > 0) && (i_step % n_opt == 0)) { cpu_time_old = cpu_time; cpu_time = cpu(); elapsed_time = cpu_time - cpu_time_old; optimize_displacement(n_atoms, &displ_max, &displ_max_old, elapsed_time, &displ_efficiency, &sum_displ2, displ_cutoff); fprintf(stderr, "\n\ni_step = %d: Accepted moves = %12.8f, displ_max = %12.8f\n", i_step, (double)n_accept / (double)n_trial, displ_max); } /* Draw system. */ if (graph_switch && n_dim == 2) redraw_2d(dpy, win, doubleBuffer, qobj, n_atoms, r, h, radius, resph); else if (graph_switch && n_dim == 3) redraw_3d(dpy, win, doubleBuffer, qobj, n_atoms, r, h, radius, resph); } /* Print final energy. */ fprintf(stderr, "\n\nFinal\n"); fprintf(stderr, "\n\nPotential energy = %12.8f\n", pot_energy); fprintf(stderr, "\n\nAccepted moves = %12.8f\n", (double)n_accept / (double)n_trial); /* Close file */ fclose(fp); /* Exit */ return(0); } mc.c (part 2)

#include "test.h" #include "compute_pot.h" double compute_pot(int n_dim, int n_atoms, double **s, double *h, double sigma2, double four_epsilon, double r_cutoff2) { int i, i_atom, j_atom; double u, r_pair_mag2, rho2, rho6, rho12, factor; static int first_call = 1; static double *s_i, *s_pair, *r_pair; /* Allocate memory for local arrays the first time the routine is called. */ if (first_call) { s_i = (double*) allocate_1d_array(n_dim, sizeof(double)); s_pair = (double*) allocate_1d_array(n_dim, sizeof(double)); r_pair = (double*) allocate_1d_array(n_dim, sizeof(double)); first_call = 0; } /* Zero Lennard-Jones potential energy and forces. */ u = 0.0; /* Loop over first atom. */ for (i_atom = 0; i_atom < n_atoms - 1; ++i_atom) { /* Get i_atom scaled coordinates. */ for (i = 0; i < n_dim; ++i) s_i[i] = s[i_atom][i]; comput_pot.c (part 1)

/* Loop over second site. */ for (j_atom = i_atom + 1; j_atom < n_atoms; ++j_atom) { /* Compute pair separation vector and squared pair separation. */ r_pair_mag2 = 0.0; for (i = 0; i < n_dim; ++i) { s_pair[i] = s[j_atom][i] - s_i[i]; s_pair[i] -= NINT(s_pair[i]); r_pair[i] = h[i] * s_pair[i]; r_pair_mag2 += SQR(r_pair[i]); } /* Compute interaction if pair separation is less than the interaction cutoff. */ if (r_pair_mag2 < r_cutoff2) { /* Add contributions to potential energy and forces. */ rho2 = sigma2 / r_pair_mag2; rho6 = CUBE(rho2); rho12 = SQR(rho6); u += four_epsilon * (rho12 - rho6); } return u; /* Return potential energy. */ } comput_pot.c (part 2)

/* This routine carries out a single Monte Carlo cycle, comprising only of Monte Carlo atom move. Output: particle positions and potential energy are modified on output */ #include "test.h" #include "mc_cycle.h" #include "atom_move.h" void mc_cycle(int n_dim, int n_atoms, double **r, double **s, double displ_max, double *h, double *h_inv, double temp, double sigma2, double four_epsilon, double r_cutoff2, long *seed, double *u_pot, double *sum_displ2, int *n_trial, int *n_accept) { int i_move; /* Loop over trial Monte Carlo moves (we only move atoms here). */ for (i_move = 0; i_move < n_atoms; ++i_move) { /* Make trial move. */ ++(*n_trial); *n_accept += atom_move(n_dim, n_atoms, r, s, displ_max, h, h_inv, temp, sigma2, four_epsilon, r_cutoff2, seed, u_pot, sum_displ2); } return; } mc_cycle.c

/* This routine generates a trial displacement of an interaction atom and accepts it based on the Metropolis criterion. Output: the return value is 1 if the move was accepted and 0 otherwise. */ #include "test.h" #include "compute_pot_single.h" #include "periodic_boundary_conditions_single.h" #include "ran3.h" int atom_move(int n_dim, int n_atoms, double **r, double **s, double displ_max, double *h, double *h_inv, double temp, double sigma2, double four_epsilon, double r_cutoff2, long *seed, double *u_pot, double *sum_displ2) { int i, i_atom, accept; double u_old, u_new, delta_u; static int first_call = 1; static double *r_old, *s_old, *displ; /* Allocate memory for local arrays the first time the routine is called. */ if (first_call) { r_old = (double*) allocate_1d_array(n_dim, sizeof(double)); s_old = (double*) allocate_1d_array(n_dim, sizeof(double)); displ = (double*) allocate_1d_array(n_dim, sizeof(double)); first_call = 0; } atom_move.c (pt. 1)

/* Select an atom at random. */ i_atom = (int) (ran3(seed) * n_atoms); if (i_atom == n_atoms) i_atom -= 1; /* Store current position and potential energy of selected site. */ for (i = 0; i < n_dim; ++i) { r_old[i] = r[i_atom][i]; s_old[i] = s[i_atom][i]; } u_old = compute_pot_single(n_dim, i_atom, n_atoms, s, h, sigma2, four_epsilon, r_cutoff2); /* Generate random displacement within hypercube of size displ_max. */ for (i = 0; i < n_dim; ++i) { displ[i] = displ_max * (ran3(seed) - 0.5); r[i_atom][i] += displ[i]; } /* Apply periodic boundary conditions. */ periodic_boundary_conditions_single(n_dim, h, h_inv, r[i_atom], s[i_atom]); /* Compute trial potential energy. */ u_new = compute_pot_single(n_dim, i_atom, n_atoms, s, h, sigma2, four_epsilon, r_cutoff2); atom_move.c (pt. 2)

For a new configuration of the same volume V and number of molecules N, displace a randomly selected atom to a point chosen with uniform probability inside a cubic volume of edge 2  centered on the current position of the atom. Examine underlying transition probability to formulate the acceptance criterion ? Select an atom at random. Consider a region centered at it. Move atom to a point chosen uniformly in region. Consider acceptance of new configuration. 22 Step 1Step 2Step 3Step 4 general hitherto David A. Kofke, SUNY Buffalo 2-Dimensional Lennard-Jones Simple Liquid (Off-Lattice)

/* Compute change in potential energy and accept move using Metropolis criterion. */ delta_u = u_new - u_old; if (delta_u <= 0.0) accept = 1; else accept = ran3(seed) < exp(- delta_u / temp); /* Update system potential energy if trial move is accepted. Otherwise, reset variables. */ if (accept) { *u_pot += delta_u; for (i = 0; i < n_dim; ++i) *sum_displ2 += SQR(displ[i]); } else { for (i = 0; i < n_dim; ++i) { r[i_atom][i] = r_old[i]; s[i_atom][i] = s_old[i]; } /* Return 1 if trial move is accepted, 0 otherwise. */ return accept; } atom_move.c (pt. 3)

/* Compute potential energy of i_atom using an all pair search. */ #include "test.h" #include "compute_pot_single.h" double compute_pot_single(int n_dim, int i_atom, int n_atoms, double **s, double *h, double sigma2, double four_epsilon, double r_cutoff2) { int i, j_atom; double u, r_pair_mag2, rho2, rho6, rho12, factor; static int first_call = 1; static double *s_i, *s_pair, *r_pair; /* Allocate memory for local arrays the first time the routine is called. */ if (first_call) { s_i = (double*) allocate_1d_array(n_dim, sizeof(double)); s_pair = (double*) allocate_1d_array(n_dim, sizeof(double)); r_pair = (double*) allocate_1d_array(n_dim, sizeof(double)); first_call = 0; } /* Zero Lennard-Jones potential energy and forces. */ u = 0.0; /* Get i_atom scaled coordinates. */ for (i = 0; i < n_dim; ++i) s_i[i] = s[i_atom][i]; comput_pot_single.c (part 1)

/* Loop over atoms. */ for (j_atom = 0; j_atom < n_atoms; ++j_atom) { if (j_atom != i_atom) { /* Compute pair separation vector and squared pair separation. */ r_pair_mag2 = 0.0; for (i = 0; i < n_dim; ++i) { s_pair[i] = s[j_atom][i] - s_i[i]; s_pair[i] -= NINT(s_pair[i]); r_pair[i] = h[i] * s_pair[i]; r_pair_mag2 += SQR(r_pair[i]); } /* Compute interaction if pair separation is less than the interaction cutoff. */ if (r_pair_mag2 <= r_cutoff2) { /* Add contributions to potential energy and forces. */ rho2 = sigma2 / r_pair_mag2; rho6 = CUBE(rho2); rho12 = SQR(rho6); u += four_epsilon * (rho12 - rho6); } return u; /* Return potential energy of atom i_atom. */ } comput_pot_single.c (part 2)

/* This routine optimizes displacement moves for a Monte Carlo simulation by maximizing the displacement efficiency, defined as the cumulative squared displacement per cpu second. output: displ_max, displ_max_old, displ_efficiency, and sum_displ2 are modified on return. */ #include "test.h" #include "optimize_displacement.h" #include "displacement_efficiency.h" #define SCALE_FACTOR 1.1 void optimize_displacement(int n_atoms, double *displ_max, double *displ_max_old, double elapsed_time, double *displ_efficiency, double *sum_displ2, double displ_cutoff) { double displ_efficiency_old, damping_factor, deriv; /* Save old displacement efficiency. */ displ_efficiency_old = *displ_efficiency; /* Calculate new displacement efficiency. */ *displ_efficiency = displacement_efficiency(n_atoms, elapsed_time, sum_displ2); /* Include damping factor to prevent runaway at low densities. */ damping_factor = exp(- *displ_max / displ_cutoff); *displ_efficiency *= damping_factor; optimize_displacement.c (pt. 2)

fprintf(stdout, " displ_max_old = %g, displ_efficiency_old = %g / cpu s\n", *displ_max_old, displ_efficiency_old); fprintf(stdout, " displ_max = %g, displ_efficiency = %g / cpu s\n", *displ_max, *displ_efficiency); /* Estimate derivative of displacement efficiency with respect to maximum displacement. */ if (*displ_max == *displ_max_old) deriv = 0.0; else deriv = (*displ_efficiency - displ_efficiency_old) / (*displ_max - *displ_max_old); /* Adjust maximum displacement. */ *displ_max_old = *displ_max; if (deriv < 0.0) *displ_max /= SCALE_FACTOR; else *displ_max *= SCALE_FACTOR; fprintf(stdout, " new displ_max = %g\n\n", *displ_max); return; } #undef SCALE_FACTOR optimize_displacement.c (pt. 2)

/* This routine calculates the atom displacement efficiency for a Monte Carlo simulation, defined as the cumulative squared object displacement per cpu second. output: efficiency (return value) sum_displ2 is modified on return. */ #include "test.h" #include "displacement_efficiency.h" double displacement_efficiency(int n_atoms, double elapsed_time, double *sum_displ2) { double efficiency; /* Calculate efficiency, defined as the cumulative squared atom displacement per cpu second. */ efficiency = *sum_displ2 / (n_atoms * elapsed_time); /* Zero displacement accumulator. */ *sum_displ2 = 0.0; return efficiency; } optimize_efficiency.c

/* This routine calculates the atom displacement efficiency for a Monte Carlo simulation, defined as the cumulative squared object displacement per cpu second. output: efficiency (return value) sum_displ2 is modified on return. */ #include "test.h" #include "displacement_efficiency.h" double displacement_efficiency(int n_atoms, double elapsed_time, double *sum_displ2) { double efficiency; /* Calculate efficiency, defined as the cumulative squared atom displacement per cpu second. */ efficiency = *sum_displ2 / (n_atoms * elapsed_time); /* Zero displacement accumulator. */ *sum_displ2 = 0.0; return efficiency; } optimize_efficiency.c

#include "test.h" #include "periodic_boundary_conditions.h" void periodic_boundary_conditions(int n_dim, int n_atoms, double *h, double *h_inv, double **r, double **s) { int i, i_object; for (i_object = 0; i_object < n_atoms; ++i_object) { /* Compute scaled coordinate and apply periodic boundary conditions. */ for (i = 0; i < n_dim; ++i) { s[i_object][i] = h_inv[i] * r[i_object][i]; s[i_object][i] -= NINT(s[i_object][i]); } /* Recompute real coordinates accounting for periodic boundary conditions. */ for (i = 0; i < n_dim; ++i) r[i_object][i] = h[i] * s[i_object][i]; } return; } periodic_boundary_conditions.c

#include "test.h" #include "periodic_boundary_conditions_single.h" void periodic_boundary_conditions_single(int n_dim, double *h, double *h_inv, double *r, double *s) { int i; /* Compute scaled coordinate and apply periodic boundary conditions. */ for (i = 0; i < n_dim; ++i) { s[i] = h_inv[i] * r[i]; s[i] -= NINT(s[i]); } /* Recompute real coordinates accounting for periodic boundary conditions. */ for (i = 0; i < n_dim; ++i) r[i] = h[i] * s[i]; return; } periodic_boundary_conditions_single.c