P. 1
MD-LJasdf

MD-LJasdf

|Views: 42|Likes:
asdafsdfj kja;sdkfja;skdfja;kdjf;akdj;fakdjf;akdj;falfaskdjad;aldfj;afjaskdfj;askfj;askdjf;adjkfdkjf;askdjf;askdfja;skdfasdfasdf asdfdfjdkjfkdjfkdjfkdkfjkadjldfj
asdafsdfj kja;sdkfja;skdfja;kdjf;akdj;fakdjf;akdj;falfaskdjad;aldfj;afjaskdfj;askfj;askdjf;adjkfdkjf;askdjf;askdfja;skdfasdfasdf asdfdfjdkjfkdjfkdjfkdkfjkadjldfj

More info:

Published by: Xristoforos Kolomvos on Apr 06, 2013
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

01/23/2014

pdf

text

original

2.

370 Project Report

Molecular Dynamics Simulation of a Lennard-Jones Fluid
Bolin Liao In this project, a molecular dynamics study is carried out on a Lennard-Jones fluid. Main algorithms implemented and their basic features include: 1) Cell list based force calculation is used to speed up the simulation and save computation resource; 2) Nose-Hoover thermostat is added to maintain the system temperature within a reasonable fluctuation range (the impace of different “thermostat mass” is also studied), with Beeman predictor-corrector integration algorithm to shorten the time needed for reaching equilibrium; 3) Long range corrections are added when calculating total potential energy and pressure, and good agreements are achieved between MD and Monte Carlo simulation results; 3) Brownian dynamics simulation is carried out to measure the diffusion coefficient, and good agreement is achieved when compared to experiment data. In the following parts of this report, details of the algorithms and data structures that are used in each stage of this simulation will be presented, while the complete codes attached as an appendix. The codes are written in Fortran.

1. Initialization
Two purposes are to be achieved in the initialization stage (SUBROUTINE init). The first is to arrange the atoms in a simple cubic structure, as their initial positions, and the second is to assign velocities from a Maxwell distribution to each atom, and rescale them in order to obtain desired temperature and guarantee a rest center of mass. The arrangement of atoms is straightforward. For generating velocities from a Maxwell distribution, a polar form Box-Muller algorithm is used to generate a Gaussian distribution from 2-dimensional uniform distribution, and then all velocities are rescaled to achieve zero average velocity and correct temperature. Codes:
FUNCTION rangauss() !Polar form Box-Muller Gaussian random number generator REAL*8 ran_uniform, rangauss, v1, v2, rsq 100 CALL RANDOM_NUMBER(v1) v1=2.0*v1-1.0 CALL RANDOM_NUMBER(v2) v2=2.0*v2-1.0 rsq=v1*v1+v2*v2 IF (rsq .GE. 1.0 .OR. rsq .LE. 0.0) GOTO 100

rangauss=v1*SQRT(-2.0*LOG(rsq)/rsq) RETURN END !---------------------------------------------------------------------------!---------------------------------------------------------------------SUBROUTINE init (temp,rho,pos,vel,len) USE constants IMPLICIT NONE !assign initial positions and velocities to the atoms REAL*8 temp !temp: Temperature of the simulation REAL*8 rho !rho: Number density of the simulation REAL*8 pos(dim,num) !Position record matrix REAL*8 vel(dim,num) !Velocity record matrix REAL*8 rangauss !Gaussian random number generator REAL*8 vol !volume of the system REAL*8 len !length of the box REAL*8 gsize !grid size of a unit cell INTEGER num_pd !number of particles per dimension INTEGER i,j,k !control variable for the loops INTEGER n !label of particles REAL*8 v_sum(dim) !average velocity REAL*8 v2_sum !mean-square velocity REAL*8 sf !temperature scaling factor vol = num/rho len = vol ** (1.0/3.0) num_pd = INT(num ** (1.0/3.0)) gsize = len/num_pd !position initialization: arrange atoms in a single cubic structure n = 1 outer: DO i = 1,num_pd DO j = 1,num_pd DO k = 1,num_pd if (n .GT. num) EXIT outer pos(1,n) = (i-1)*gsize pos(2,n) = (j-1)*gsize pos(3,n) = (k-1)*gsize n = n + 1 END DO END DO END DO outer !velocity initialization: Maxwell distribution with rescaling v_sum(1:dim)=0; v2_sum = 0; DO i = 1,num vel(1,i) = rangauss() vel(2,i) = rangauss() vel(3,i) = rangauss() v_sum(1) = v_sum(1) + vel(1,i) v_sum(2) = v_sum(2) + vel(2,i) v_sum(3) = v_sum(3) + vel(3,i) v2_sum = v2_sum + vel(1,i)*vel(1,i)+vel(2,i)*vel(2,i)+vel(3,i)*vel(3,i) END DO v_sum(1) = v_sum(1)/REAL(num) !average velocity

i) = (vel(3.i)*vel(1.i)*vel(2.i)-v_sum(1))*sf vel(2.i) END DO RETURN END SUBROUTINE init After initialization.i)+vel(2. the atom positions are as shown below: Initialized Position 12 10 8 z 6 4 2 0 10 5 y 0 0 2 4 x 6 8 10 12 .i)-v_sum(2))*sf vel(3.0*temp/v2_sum) !scaling factor to desired temperature !Rescale the velocity to set the initial temperature v2_sum = 0 DO i = 1.i) = (vel(2.num vel(1.i)+vel(3.v_sum(2) = v_sum(2)/REAL(num) v_sum(3) = v_sum(3)/REAL(num) v2_sum = v2_sum/REAL(num) !average velocity square sf = SQRT(3.i) = (vel(1.i)*vel(3.i)-v_sum(3))*sf v2_sum = v2_sum + vel(1.

996 0.04 0.16 0. which matches the given conditions very well. “Understanding Molecular Simulation”. and insert the atom into the link list of the corresponding cell that it belongs to.18 Initial Distribution Gaussian mean: -6e-17. locate them to certain cell.1 0. 2002 nd . while the label of the next atom in the link list is stored in the matrix link.06 0. 1 D. Each cell has a corresponding link list that stores the information of what atoms are located in this cell. The basic data structure used in my program is a link list1. 0.The velocity distribution is shown below: We can tell from this distribution fitting plot that the average value of velocities is zero and the variance of the distribution is 4. variance 4.12 Density 0. pp550-552.08 0. a cell list is implemented. Then scan all the atoms. Cell list and force calculation To speed up force calculation. which follows the standard routine of operations on a link list.14 0.996 (the given temperature is 5). Frankel. B. the head of which is stored in the matrix cell. Smit.02 0 -6 -4 -2 0 Data 2 4 6 2. All elements of the cell matrix are initialized to zero. 2 edition. Then a cell list is built up that contains the labels of the atoms that are in certain cell. The link list consists of two matrices: cell and link. First the simulation volume is divided to smaller cells with size equal to or slightly larger than the cut-off radius.

The nearest 26 cells of the cell also need to be scanned to calculate forces on a certain atom. which speeds up the force calculation a lot.num) INTEGER ncel !number of cells per dimension REAL*8 rcel !size of a cell INTEGER n !label of particles INTEGER i.cellz !id of the cell for certain atom INTEGER link(num) INTEGER cell(0:ncel-1. END DO RETURN END SUBROUTINE cell_list After setting up the cell list.rcel.celly.cellz) cell(cellx.num !scan all atoms !locate the atom to certain cell cellx = INT(pos(1. and finally move on to the next atom in the link list by referring to matrix link.n)/rcel) !insert the atom into the link list of the corresponding cell link(n) = cell(cellx.0:ncel-1.n)/rcel) cellz = INT(pos(3. I set up a signal matrix called period to mark whether a periodic boundary condition is encountered and adjust the position of the corresponding atoms accordingly. Another complication of force calculation has to do with the periodic boundary condition. and locate it to certain cell.n)/rcel) celly = INT(pos(2.ncel. . indicating the search of this cell is finished.0:ncel-1) !initialize the cell list cell(0:ncel-1.celly. until reaching the tail of the link list.cell.Codes: (set up cell list) SUBROUTINE cell_list (pos.link) !generating cell_list USE constants IMPLICIT NONE REAL*8 pos(dim. First scan all the atoms. force calculation is straight forward.0:ncel-1) = 0 !set up the cell list DO n = 1. By this means.cellz)=n.k !loop control INTEGER cellx.0:ncel-1. which is the first atom in the cell.celly.j. it is not necessary to scan all other atoms to calculate the force on a certain atom. which is marked by 0. instead only 27 cells need to be scanned. then calculate the potential energy and forces between the two atoms. then find the head of the link list of the cell by referring to matrix cell.

n)=0 force(3.ii.n)/rcel) !find which cell this atom sits in celly = INT(pos(2.num) !force matrix REAL*8 len !size of the box INTEGER n !labels for atoms INTEGER cellx.ncel period(1) = 2 END IF IF(jj .radius6.uij !potential energy for each atom DO n = 1.kk !loop control INTEGER period(dim) !flag for periodic b.force. ncel-1) THEN jj = jj .ncel period(2) = 2 .ncel. 0:no periodic. 0) THEN ii = ii + ncel period(1) = 1 END IF IF(ii .link.radius6i !square of the distance REAL*8 potential(num).jj.num) !position matrix INTEGER cell(0:ncel-1.cell.Codes: (force calculation) SUBROUTINE force_calculation (pos.rcel.n)=0 potential(n)=0 !initalize the internal energy DO i = cellx-1.celly.celly+1 DO k = cellz-1.n)/rcel) force(1.m.len.GT.0:ncel-1. !implementing periodic boundary condition period(1:dim)=0 !intialize the flag !adjust the cell id and set up the flags IF(ii .n)=0 !initialize forces force(2.2:upper bound REAL*8 distance(dim) !distance in each dimensions REAL*8 radius2.LT.num !consider the atom labeled n cellx = INT(pos(1. kk=k.n)/rcel) cellz = INT(pos(3. !keep track of the control variable for recovery jj=j.j.cellx+1 !scan the nearest 27 cells DO j = celly-1.potential) USE constants IMPLICIT NONE REAL*8 pos(dim.cellz+1 ii=i.LT.k.cellz !id of the cell for certain atom REAL*8 pos1(dim) !the positon of the other atom that interacts with the current atom INTEGER id !the label of the other atom INTEGER i. 0) THEN jj = jj + ncel period(2) = 1 END IF IF(jj .GT.0:ncel-1) !cell list INTEGER link(num) !link list INTEGER ncel !number of cells per dimension REAL*8 rcel !size of cells REAL*8 force(dim.c. ncel-1) THEN ii = ii .1:lower bound.

EQ.id)-len ELSE IF (period(m) .jj.EQ. 0) THEN pos1(m)=pos(m. ncel-1) THEN kk = kk .dim force(m.GT.EQ. 1) THEN pos1(m)=pos(m.ncel period(3) = 2 END IF !start from the head of the chain id=cell(ii.kk) DO WHILE (id .0/radius6 !calculate potential energy uij = 4*radius6i*(radius6i-1) potential(n) = potential(n) + uij .dim IF (period(m) .LT.ucut !caululate forces DO m = 1. rcut*rcut) THEN id = link(id) CYCLE END IF radius6 = radius2**3 radius6i = 1.n) + distance(m)*6*(uij+4*(radius6i**2))/radius2 END DO !move on to the next atom in the chain id = link(id) END DO END DO END DO END DO END DO END SUBROUTINE force_calculation . continue to the next atom radius2 = distance(1)*distance(1)+distance(2)*distance(2)+distance(3)*distance(3) IF (radius2 . 2) THEN pos1(m)=pos(m.EQ. 0) !if not reached the tail of the chain IF (id . n) THEN !if find the atom itself.GT. 0) THEN kk = kk + ncel period(3) = 1 END IF IF(kk .id)+len END IF !distance between the two atoms in each dimension distance(m)=pos(m.NE.END IF IF(kk .n)-pos1(m) END DO !if the atom is outside the cut-off radius.id) ELSE IF (period(m) .n) = force(m. skip id = link(id) CYCLE END IF !find the position of the interacting atom DO m=1.

num) REAL*8 vel(dim.i) + delta_pos !update the velocity vel(j. Integration of EOM Knowing the forces on each atom.i)*time_step + force(j. 2002 nd . a NoseHoover thermostat is added to the system.i) = pos(j.0*mass)*time_step*time_step !update the position.trace) !bootstrap the system using velocity Verlet algorithm USE constants IMPLICIT NONE REAL*8 pos(dim. Since in Beeman algorithm the forces in the previous time point are needed to launch the iteration. Since the Nose-Hoover thermostat is generally not compatible with velocity Verlet algorithm2.vel. adding up to trace sumv(1:dim)=0 !initialize the average velocity sumv2=0 !initialize the average squared velocity DO i = 1.i) = vel(j. Codes: (launch the system at the first step) SUBROUTINE bootstrap(pos.i) . pp535.i) = trace(j.len.i)*vel(j.j !loop control REAL*8 sumv(dim) !summation of velocity REAL*8 sumv2 !summation of velocity square REAL*8 sf !temperature scaling factor REAL*8 len !box size REAL*8 temp !temperature REAL*8 trace(dim.i) = pos(j.LT.num) REAL*8 force(dim.i) !adjust position according to periodic boundary conditions IF (pos(j. 0) pos(j.force.INT(pos(j. 2 edition.i) = pos(j.i) .i)/mass*time_step sumv(j) = sumv(j) + vel(j.temp. Smit. the Beeman predictor-corrector algorithm is chosen as the integration scheme. len) pos(j.GT.i)/len)*len + len IF (pos(j.i) .i) + force(j.i)/(2. and keep track of the trace(for diffusion experiment) pos(j.3.i)/len)*len END DO END DO !rescaling the velocity again sumv(1)=sumv(1)/REAL(num) sumv(2)=sumv(2)/REAL(num) sumv(3)=sumv(3)/REAL(num) sumv2=sumv2/REAL(num) 2 D. B. a bootstrap subroutine using velocity Verlet algorithm is designed to launch the system at the first step. the next step is to integrate the equations of motion to make the system start evolving with time.num) INTEGER i. “Understanding Molecular Simulation”.i) .dim !calculate the relative motion delta_pos = vel(j.i) sumv2 = sumv2 + vel(j.INT(pos(j.num) !trace matrix REAL*8 delta_pos !the relative translation of position. Frankel. To keep a stable temperature along the simulation.num DO j = 1.i) + delta_pos trace(j.

sf = SQRT(3.i) END DO END DO WRITE (*. the Beeman algorithm is used to integrate the equations of motion.i)-sumv(j))*sf sumv2 = sumv2 + vel(j.i)*vel(j.num DO j = 1. sumv2/REAL(num)/3.*) 'Bootstrap Temperature: ' .0*temp/sumv2) sumv2=0 DO i = 1. The “mass” of the thermostat determines the feedback sensitivity and thus the temperature fluctuation. The thermostat feedback variable ksi evolves with time.0 END SUBROUTINE bootstrap After Boostrap 12 10 8 z 6 4 2 0 10 5 y 0 0 2 4 x 6 8 10 12 For subsequent time steps.dim vel(j. . while the time derivative of ksi depends on the difference between the actual temperature and the given temperature. The Nose-Hoover thermostat is added in the force calculation process in a Beeman iteration.i) = (vel(j. The impacts of different thermostat mass are evaluated in this project.

j !loop control REAL*8 trace(dim.INT(pos(j.i) = vel(j.num) INTEGER cell(0:ncel-1.num) !velp:the predicted velocity !forces at the previous.rcel.cell. 0) pos(j.Codes (Beeman integration algorithm) SUBROUTINE beeman(pos.dim !calculate forces incorporating thermostat force2(j.0:ncel-1.i) .i)=force2(j.dim !calculate relative motion delta_pos = vel(j.num) !trace of the atoms REAL*8 delta_pos !relative motion DO i = 1.i) .num).i) = pos(j.trace) !integrate the EOM using Beeman's predictor-corrector algorithm with NoseHoover thermostat USE constants IMPLICIT NONE REAL*8 pos(dim.i)/len)*len !predicted velocities velp(j.cell.force.rcel.ncel.potential) DO i = 1.i))/mass END DO END DO !update cell list and calculate forces CALL cell_list(pos.velp(dim.i))/mass pos(j.i) = trace(j.rcel. current and the next time point REAL*8 force(dim.num).ncel.i)-force(j.len. len) pos(j.i) + delta_pos !periodic boundary conditions IF (pos(j.i)-ksi*mass*velp(j.GT.i) + time_step/2*(3*force1(j.vel.len.i) .cell.link.ncel.i)*time_step + time_step*time_step/6*(4*force1(j.i) + delta_pos trace(j.len.i) = vel(j.i)/len)*len + len IF (pos(j.i) = pos(j.num DO j = 1.link) CALL force_calculation (pos.LT.force1.potential(num) REAL*8 ksi !friction factor INTEGER i.i) = pos(j.force2.INT(pos(j.i)+5*force1(j.i))/mass END DO END DO RETURN END SUBROUTINE beeman .force2(dim.num) REAL*8 vel(dim.num DO j = 1.i)-force(j.num).i) + time_step/6*(2*force2(j.i)force(j.0:ncel-1) !cell list INTEGER link(num)!link list INTEGER ncel !number of cells per dimension REAL*8 rcel.i) !corrected velocity vel(j.ksi.i) .potential.force1(dim.link.

4 5. I tried first rescaling the system for 100 time steps. T=5) 6 Q=100 Q=10 Q=1 Q=0.5 1 1. which indicates a much more stable temperature.6 4.1 5. and played with the thermostat mass. I first tried adding Nose-Hoover thermostat at the beginning. generally two methods could be used.4 5.To maintain a stable temperature. velocity-rescaling and adding a thermostat.2 4 0 0.5 4 4.4 4.8 4. then turning on the thermostat and stopping the rescaling.5 2 2.4 4.6 4.5 t 3 3.2 4 temperature 0 1000 2000 3000 4000 5000 t 6000 7000 8000 9000 10000 . and I got the following result. Thermostat test (with rescaling) 6 5. without temperature rescaling.8 5.6 5.5 x 10 5 4 From this plot we could see relatively large fluctuations of temperature and very slow convergence.8 5.8 4.2 temperature 5 4.2 5 4.6 5. To get a more stable temperature and faster convergence. and I got the following results: Thermostat test (w/o rescaling.

The summation of the squares of the relative displacements of all the atoms is supposed to increase linearly with time. mimicking a diffusion process.potential.dim sumv2 = sumv2 + (vel(j.4. Temperature and pressure are measured as described in the project assignment.i)-v_ave(j))*(vel(j.dim v_ave(j) = v_ave(j) + vel(j.num) REAL*8 vel(dim.j !calculate average velocities v_ave(1:dim)=0 DO i = 1. the slope of which gives the diffusion coefficient.v_ave. total potential energy and diffusion coefficient are measured. measurements of the system properties could be carried out. The diffusion coefficient is measured using the random-walk model.temp1.num DO j = 1.i) END DO END DO v_ave(1) = v_ave(1)/REAL(num) v_ave(2) = v_ave(2)/REAL(num) v_ave(3) = v_ave(3)/REAL(num) !calculate temperature sumv2 = 0 DO i = 1. temperature. pxx.pressure.i)-v_ave(j)) END DO END DO temp1 = sumv2/REAL(num)/3. where the traces of each atom are recorded in a matrix called trace. pzz !current pressure REAL*8 etot !total energy of the system REAL*8 potential(num).rho) !measure system properties USE constants IMPLICIT NONE REAL*8 rho.num) REAL*8 temp1 !current temperature REAL*8 pressure. pressure.vel.vol !number density and volume REAL*8 pos(dim. psum !potential energy REAL*8 v_ave(dim) !average velocity of each dimension REAL*8 sumv2 !summation of velocity square REAL*8 radius !distance between two atoms REAL*8 force !force between two atoms INTEGER i. Codes: (measurement of the system) SUBROUTINE measure(pos. In this project.num psum = psum + potential(i) END DO etot = psum/2. pyy.num DO j = 1.etot.0/REAL(num) . Measurement After the system reaches equilibrium.0 !calculate total potential energy psum = 0 DO i = 1.

ucor.j))*(pos(1.j))*(pos(3.i)-pos(1.j)) force = 4.i)-pos(3. The long-range corrections are provided in the following two equations: ∫ ( ) ( ) ∫ ( ) Codes: (long-range corrections) !----------------------------------------------------------------SUBROUTINE long_range_correction(rho.i)-pos(3. which could be found in the appendix. Long Range Corrections Long range corrections for total potential energy and pressure are incorporated in this project.0*rcut**3)) pcor = 16.i)-pos(2.j))*force END DO END DO pressure = rho*temp1+(pxx+pyy+pzz)/3.i)-pos(2.0/(9.j)) +(pos(3.j))*(pos(2.0/vol RETURN END SUBROUTINE measure The codes for diffusion experiment are scattered in different parts of whole program.num DO j = i+1.i)-pos(1.0/(3.num radius = (pos(1.1415926*rho*(1. 5.j))*(pos(1.1415926*rho*(2.i)-pos(3.0/(9.0*rcut**9)-1.!measure the pressure vol = REAL(num)/rho pxx = 0 !configurational pressure pyy = 0 pzz = 0 DO i = 1.0*rcut**9)-1.j)) + (pos(2.0*rcut**3)) RETURN END SUBROUTINE long_range_correction !----------------------------------------------------------------- .j))*(pos(3.i)-pos(2.i)pos(2.0*3.i)-pos(1.pcor) USE constants IMPLICIT NONE !calculate the long range corrections for potential energy and pressure REAL*8 rho !numdensity of the simulation REAL*8 ucor !long range correction for potential energy REAL*8 pcor !long range correction for pressure ucor = 8.0/(radius**4)*(12/(radius**3)-6) pxx = pxx + (pos(1.0/(3.i)-pos(3.j))*(pos(2.i)-pos(1.0*3.j))*force pyy = pyy + (pos(2.j))*force pzz = pzz + (pos(3.

number density = 0.3. The convergence is fast. Test of Performance Test Conditions 1: temperature = 5. Time (T=5.5) 5 n=1000 n=8000 4 3 pressure 2 1 0 -1 0 100 200 300 400 500 time 600 700 800 900 1000 Here I show the time evolution of pressure for systems consist of 1000 and 8000 atoms respectively. n=0. . which is comparable with the Monte Carlo result (=4. The averaged pressure is around 4.6.5 Pressure Vs. the system will be in equilibrium.65). And we can see apparently less fluctuations in a larger system. generally after 100 time steps (~2 ps).

1. number density = 0. n=0. comparable with the Monte Carlo result (= -2. Time (T=5.1.37) Test Condition 2: temperature = 2. .9 Pressure (T=2.5 potential energy -2 -2.Potential Energy vs. rho=0. while the Monte Carlo gives 9.5 -3 0 100 200 300 400 500 time 600 700 800 900 1000 Potential energy measured: -2.5) -1 n=1000 n=8000 -1.9) 16 15 14 13 12 n=1000 n=8000 pressure 11 10 9 8 7 6 0 100 200 300 400 500 time 600 700 800 900 1000 The measured pressure is around 9.

5 -4 -4.01 0 0 500 1000 1500 2000 2500 time 3000 3500 4000 4500 5000 . number density = 0.06 pressure 0.5.Potential energy (T=2.05 Pressure (T=1.04 0. Test Condition 3 : temperature = 1.09 0. rho=0.1 0.05 0.07 0. while the Monte Carlo gives -5.9) -2.5 -5 0 100 200 300 400 500 time 600 700 800 900 1000 Measured potential energy is -4.03 0.05) 0.08 n=1000 n=8000 0.5 n= 8000 n= 1000 -3 Potential energy -3.02 0. rho=0.

1709 (140K).904) 12 1000 8000 11 m-3) 10 9 potential 8 7 6 5 4 0 100 200 300 400 500 time 600 700 800 900 1000 .037 Potential Energy (T=1.35 0 500 1000 1500 2000 2500 time 3000 3500 4000 4500 5000 Measured potential energy: -0.043.3 -0.25 -0.Measured pressure: 0.05 -0.478 Test Condition 4 : temperature = 1. while the Monte Carlo gives 0.2 -0. while Monte Carlo gives -0.1709. number density = 0. rho=0.904 ( Pressure ( T=1.15 -0.05) 0 n=1000 n=8000 -0.1 Potential energy -0. rho=0.34.

4 0. .7 0. which is equivalent to ⁄ .7 (197.3 0.05 0 0 0.9 1 The slope of the linear fitting is 0.5 time 0.15 0.431.25 R2 0.8 0.2 0.4 0.35 0. so the diffusion coefficient is D=0.3 0.3 MPa) Random Walk R^2 Linear Fit 0. Since the slope equals 6D in 3-dimension case.0718.2 0.1 0.6 0.Measured pressure: 4.1 0.431/6=0.

num).0) REAL*8 qmass !Nose-Hoover thermostat mass PARAMETER (qmass=10) END MODULE constants !---------------------------------------------------------------------PROGRAM md USE constants IMPLICIT NONE REAL*8 temp !assigned temperature REAL*8 temp1 !current temperature REAL*8 pressure !measured pressure REAL*8 rho !assigned number density REAL*8 pos(dim.num) !velocity matrix REAL*8 v_ave(dim) !average velocity REAL*8 len !length of the box INTEGER ncel !number of cells REAL*8 rcel !size of a cell INTEGER.:.for calculating Diffusion Coefficient REAL*8 sf !temperature scaling factor INTEGER cyc !cycle of simulation . ALLOCATABLE. DIMENSION(:.num).force1(dim.trace2 !trace of all atoms .:) :: cell !cell list INTEGER link(num) !link list for cells REAL*8 force(dim.4) REAL*8 ucut !cut-off energy PARAMETER (ucut=4.num) !force matrix REAL*8 potential(num) !potential energy REAL*8 ucor !long range correction for potential energy REAL*8 pcor !long range correction for pressure REAL*8 etot !total energy REAL*8 ksi !friction factor for Nose-Hoover thermostat REAL*8 trace(dim.num) !position matrix REAL*8 vel(dim.Appendix: The complete codes: !Molecular Dynamics Simulation of Lennard-Jones liquid !Author: Bolin Liao Date: 05/09/2011 !All Rights Reserved !Nose-Hoover Thermostat with Beeman predictor-corrector algorithm ! !--------------------------------------------------------------!define constants MODULE constants IMPLICIT NONE INTEGER num PARAMETER (num = 8000) INTEGER dim !dimension of the simulation PARAMETER (dim = 3) REAL*8 time_step !time step PARAMETER (time_step = 1.0/(rcut**6)*(1/(rcut**6)-1)) REAL*8 mass !mass of the particle PARAMETER (mass=1.e-3) REAL*8 rcut !cut-off radius PARAMETER (rcut = 2.

len.j)*trace(1.rcel.*) 'Initialization Done!' !calculate long range correction factors CALL long_range_correction(rho.etot.cell.force1.INTEGER i.potential) !bootstrap the system trace(1:dim.link.ncel.*) 'long range correction for potential:'.pos.link.potential) ksi = 0 !initialize the friction factor DO i = 1.j)*trace(3.ncel.0:ncel-1. len.*) 'Input Simulation Temperature' READ (*.F12.rho.*) 'len: '.vel.ncel.ncel. etot.j)*trace(2.potential.v_ave.num trace2 = trace2 + trace(1.link.trace) CALL cell_list(pos.vel.7.*) 'long range correction for pressure:'.200) temp1.*) temp WRITE(*.ncel.cell.7) WRITE (21.len.trace) force = force1 CALL cell_list(pos. pressure.potential.temp. pcor !initialize the cell list parameters ncel=INT(len/rcut) rcel=len/REAL(ncel) WRITE (*.cell.link) CALL force_calculation (pos.force1.j) END DO trace2 = trace2/REAL(num) 200 FORMAT (F12.rcel.dat'.'ncel: '.*) 'Input Simulation Cycle' READ (*.pressure.len.ucor.pcor) WRITE (21.7.ncel.ncel.force.rcel.link) CALL force_calculation (pos.rcel.ksi.7.*) rho WRITE(*.vel.rcel. etot.trace2 WRITE (*.link) CALL force_calculation (pos.vel. STATUS='REPLACE') !initialization CALL init (temp.temp1.cell.potential) CALL measure(pos.j) + trace(2. 200) THEN sf = SQRT(temp/temp1) vel = vel * sf .*) cyc OPEN (UNIT=21.rcel ALLOCATE (cell(0:ncel-1.0:ncel-1)) !set up cell list and calculate forces CALL cell_list(pos.cyc CALL beeman(pos.len.rho) pressure = pressure + pcor etot = etot + ucor !calculate the collective displacement to obtain diffusion coefficient trace2 = 0 DO j = 1.rcel.1:num) = 0 !initialize the trace matrix CALL bootstrap(pos.F12.200) temp1.cell.cell.force.j) + trace(3.'rcel: '.link.ncel.k !loop control WRITE (*.len) WRITE (*. pressure.LT.*) 'Input Simulation Density' READ (*.cell.rcel. FILE='test.trace2 !Rescaling till 200 time steps to turn on thermostat IF (i .len.F12.j. ucor WRITE (21.force.force1.

num_pd gsize = len/num_pd !position initialization n = 1 outer: DO i = 1.vel.n) = (j-1)*gsize pos(3.i) = rangauss() .num) !Velocity record matrix !Gaussian random number generator REAL*8 rangauss REAL*8 vol !volume of the system REAL*8 len !length of the box REAL*8 gsize !grid size of a unit cell INTEGER num_pd !number of particles per dimension INTEGER i.*) 'number of particles per side' .num) !Position record matrix vel(dim.num_pd DO k = 1.j.n) = (k-1)*gsize n = n + 1 END DO END DO END DO outer !velocity initialization v_sum(1:dim)=0.0)) !WRITE (*.ELSE ksi = ksi + (3*num+1)/qmass*(temp1-temp)*time_step END IF END DO CLOSE (UNIT=21) END PROGRAM md !---------------------------------------------------------------------!---------------------------------------------------------------------SUBROUTINE init (temp.i) = rangauss() vel(3.0/3.k !control variable for the loops INTEGER n !label of particles REAL*8 v_sum(dim) !average velocity REAL*8 v2_sum !mean-square velocity REAL*8 sf !temperature scaling factor vol = num/rho len = vol ** (1.rho.num_pd DO j = 1.len) USE constants IMPLICIT NONE REAL*8 REAL*8 REAL*8 REAL*8 temp !temp: Temperature of the simulation rho !rho: Number density of the simulation pos(dim. num) EXIT outer pos(1.0) num_pd = INT(num ** (1.GT.num_pd if (n .0/3.n) = (i-1)*gsize pos(2. v2_sum = 0.num vel(1.i) = rangauss() vel(2.pos. DO i = 1.

i)+vel(3.celly.v_sum(1) = v_sum(1) + vel(1.0:ncel-1) = 0 !set up the cell list DO n = 1.i) = (vel(2.n)/rcel) !insert the atom into the link list link(n) = cell(cellx.celly.*) v2_sum/REAL(num)/3. END DO RETURN END SUBROUTINE cell_list .celly.cellz) cell(cellx.num) INTEGER ncel !number of cells per dimension REAL*8 rcel !size of a cell INTEGER n !label of particles INTEGER i.cell.i)*vel(1.i) END DO v_sum(1) = v_sum(1)/REAL(num) !average velocity v_sum(2) = v_sum(2)/REAL(num) v_sum(3) = v_sum(3)/REAL(num) v2_sum = v2_sum/REAL(num) !average velocity square sf = SQRT(3.num vel(1.num !scan all atoms !locate the atom cellx = INT(pos(1.cellz !id of the cell for certain atom INTEGER link(num) INTEGER cell(0:ncel-1.i)-v_sum(3))*sf v2_sum = v2_sum + vel(1.0:ncel-1) !initialize the cell list cell(0:ncel-1.n)/rcel) celly = INT(pos(2.i)+vel(2.link) !generating cell_list USE constants IMPLICIT NONE REAL*8 pos(dim.i)+vel(2.0:ncel-1.i)-v_sum(1))*sf vel(2.0*temp/v2_sum) !scaling factor to desired temperature !Rescale the velocity to set the initial temperature v2_sum = 0 DO i = 1.i) END DO !WRITE (21.0 RETURN END SUBROUTINE init !---------------------------------------------------------------------------!---------------------------------------------------------------------------SUBROUTINE cell_list (pos.i) = (vel(3.i)*vel(2.j.i) v_sum(2) = v_sum(2) + vel(2.0:ncel-1.i)*vel(3.i)*vel(1.i)*vel(3.i) v_sum(3) = v_sum(3) + vel(3.rcel.ncel.i)+vel(3.i) v2_sum = v2_sum + vel(1.n)/rcel) cellz = INT(pos(3.k !loop control INTEGER cellx.i)*vel(2.cellz)=n.i)-v_sum(2))*sf vel(3.i) = (vel(1.

celly.force.0:ncel-1.jj. 2: upper bound REAL*8 distance(dim) !distance in each dimensions REAL*8 radius2.GT. 0) THEN jj = jj + ncel period(2) = 1 END IF . 1: lower bound. 0) THEN ii = ii + ncel period(1) = 1 END IF IF(ii .cell. !keep track of the control variable for recovery jj=j.0:ncel-1) !cell list INTEGER link(num) !link list INTEGER ncel !number of cells per dimension REAL*8 rcel !size of cells REAL*8 force(dim.radius6.len.rcel.!---------------------------------------------------------------------------!---------------------------------------------------------------------------SUBROUTINE force_calculation (pos.cellx+1 !scan the nearest 27 cells DO j = celly-1. !implementing periodic boundary condition period(1:dim)=0 !intialize the flag !adjust the cell id and set up the flags IF(ii .celly+1 DO k = cellz-1.num !consider the atom labeled n cellx = INT(pos(1.cellz+1 ii=i.ncel period(1) = 2 END IF IF(jj .radius6i !square of the distance REAL*8 potential(num).LT.j.num) !force matrix REAL*8 len !size of the box INTEGER n !labels for atoms INTEGER cellx. ncel-1) THEN ii = ii .n)/rcel) force(1. kk=k.m.uij !potential energy for each atom DO n = 1.num) !position matrix INTEGER cell(0:ncel-1.k.cellz !id of the cell for certain atom REAL*8 pos1(dim) !the positon of the other atom that interacts with the current atom INTEGER id !the label of the other atom INTEGER i.n)=0 !initialize forces force(2.kk !loop control INTEGER period(dim) !flag for periodic boundary condition 0:no periodic.n)/rcel) !find which cell this atom sits in celly = INT(pos(2.LT.link.n)/rcel) cellz = INT(pos(3.potential) USE constants IMPLICIT NONE REAL*8 pos(dim.n)=0 potential(n)=0 !initalize the internal energy DO i = cellx-1.ncel.n)=0 force(3.ii.

EQ.kk) DO WHILE (id .id)+len END IF distance(m)=pos(m.ucut !caululate forces DO m = 1.dim force(m. 2) THEN pos1(m)=pos(m. skip id = link(id) CYCLE END IF !find the position of the interacting atom DO m=1.n) = force(m.n)-pos1(m) !distance between the two atoms in each dimension END DO !if the atom is outside the cut-off radius.id)-len ELSE IF (period(m) .EQ. 1) THEN pos1(m)=pos(m.NE. ncel-1) THEN kk = kk .id) ELSE IF (period(m) . rcut*rcut) THEN id = link(id) CYCLE END IF radius6 = radius2**3 radius6i = 1.GT. 0) THEN pos1(m)=pos(m. 0) !if not reached the tail of the chain IF (id .dim IF (period(m) .LT. 0) THEN kk = kk + ncel period(3) = 1 END IF IF(kk .EQ.ncel period(3) = 2 END IF !start from the head of the chain id=cell(ii.GT.GT.n) + distance(m)*6*(uij+4*(radius6i**2))/radius2 END DO !move on to the next atom in the chain id = link(id) END DO END DO END DO END DO END DO END SUBROUTINE force_calculation .EQ. continue to the next atom radius2 = distance(1)*distance(1)+distance(2)*distance(2)+distance(3)*distance(3) IF (radius2 . n) THEN !if find the atom itself.0/radius6 !calculate potential energy uij = 4*radius6i*(radius6i-1) potential(n) = potential(n) + uij . ncel-1) THEN jj = jj .ncel period(2) = 2 END IF IF(kk .jj.IF(jj .

0) pos(j.i) = trace(j.num DO j = 1.i) + delta_pos trace(j.vel.num) INTEGER i.i) = vel(j. len) pos(j.trace) !bootstrap the system using velocity Verlet algorithm USE constants IMPLICIT NONE REAL*8 pos(dim.i)/len)*len + len IF (pos(j.dim vel(j.i) = (vel(j.0*mass)*time_step*time_step !update the position.i)*vel(j.0 END SUBROUTINE bootstrap . adding up to trace sumv(1:dim)=0 !initialize the average velocity sumv2=0 !initialize the average squared velocity DO i = 1.i)*time_step + force(j.num) !trace matrix REAL*8 delta_pos !the relative translation of position.*) 'Bootstrap Temperature: ' .i) = pos(j.i) .i)-sumv(j))*sf sumv2 = sumv2 + vel(j.len.INT(pos(j.i) . sumv2/REAL(num)/3.0*temp/sumv2) sumv2=0 DO i = 1.j !loop control REAL*8 sumv(dim) !summation of velocity REAL*8 sumv2 !summation of velocity square REAL*8 sf !temperature scaling factor REAL*8 len !box size REAL*8 temp !temperature REAL*8 trace(dim.temp.i) .i) = pos(j.i)/mass*time_step sumv(j) = sumv(j) + vel(j. and keep track of the trace(for diffusion experiment) pos(j.force.i) + force(j.dim !calculate the relative move delta_pos = vel(j.GT.i) = pos(j.num DO j = 1.i)/(2.num) REAL*8 vel(dim.INT(pos(j.i) !adjust position according to periodic boundary conditions IF (pos(j.!---------------------------------------------------------------------------!---------------------------------------------------------------------------SUBROUTINE bootstrap(pos.LT.i) + delta_pos !update the velocity vel(j.i) .num) REAL*8 force(dim.i) sumv2 = sumv2 + vel(j.i)/len)*len END DO END DO !rescaling the velocity again sumv(1)=sumv(1)/REAL(num) sumv(2)=sumv(2)/REAL(num) sumv(3)=sumv(3)/REAL(num) sumv2=sumv2/REAL(num) sf = SQRT(3.i) END DO END DO WRITE (*.i)*vel(j.

dim !calculate forces incorporating thermostat force2(j.i))/mass END DO END DO !update cell list and calculate forces CALL cell_list(pos.velp(dim.INT(pos(j.LT.i)force(j.i) + time_step/6*(2*force2(j.num DO j = 1.force.i) = pos(j.dim !calculate relative motion delta_pos = vel(j.force1.0:ncel-1) !cell list INTEGER link(num)!link list INTEGER ncel !number of cells per dimension REAL*8 rcel.num) REAL*8 vel(dim.rcel.num).i)/len)*len + len IF (pos(j. current and the next time point REAL*8 force(dim.i) .force2.force2(dim.i) = trace(j. 0) pos(j.num).rcel.i)*time_step + time_step*time_step/6*(4*force1(j.num DO j = 1.i)+5*force1(j.num).num) !velp:the predicted velocity !forces at the previous. len) pos(j.vel.i))/mass END DO END DO RETURN END SUBROUTINE beeman .i) .i) + delta_pos !periodic boundary conditions IF (pos(j.i) + time_step/2*(3*force1(j.i) + delta_pos trace(j.len.len.link.ncel.potential) DO i = 1.ksi.force1(dim.cell.link) CALL force_calculation (pos.len.i) .trace) !integrate the EOM using Beeman's predictor-corrector algorithm with NoseHoover thermostat USE constants IMPLICIT NONE REAL*8 pos(dim.INT(pos(j.cell.i) = pos(j.j !loop control REAL*8 trace(dim.i)=force2(j.!---------------------------------------------------------------------------!---------------------------------------------------------------------------SUBROUTINE beeman(pos.i) .i) !corrected velocity vel(j.i) = vel(j.i)-force(j.cell.i)-force(j.GT.ncel.potential(num) REAL*8 ksi !friction factor INTEGER i.link.i) = pos(j.i)/len)*len !predicted velocities velp(j.i))/mass pos(j.0:ncel-1.potential.num) INTEGER cell(0:ncel-1.ncel.i)-ksi*mass*velp(j.i) = vel(j.num) !trace of the atoms REAL*8 delta_pos !relative motion DO i = 1.rcel.

potential.vol !number density and volume REAL*8 pos(dim.!---------------------------------------------------------------------------!---------------------------------------------------------------------------SUBROUTINE measure(pos.i)-pos(3.temp1.j))*(pos(2. pxx.0/REAL(num) !measure the pressure vol = REAL(num)/rho pxx = 0 !configurational pressure pyy = 0 pzz = 0 DO i = 1.v_ave.num) REAL*8 temp1 !current temperature REAL*8 pressure.num psum = psum + potential(i) END DO etot = psum/2.dim v_ave(j) = v_ave(j) + vel(j.num) REAL*8 vel(dim. pyy.i)-pos(3.0 !calculate total potential energy psum = 0 DO i = 1.etot.num DO j = 1.vel.j)) +(pos(3.pressure.i) END DO END DO v_ave(1) = v_ave(1)/REAL(num) v_ave(2) = v_ave(2)/REAL(num) v_ave(3) = v_ave(3)/REAL(num) !calculate temperature sumv2 = 0 DO i = 1.j !calculate average velocities v_ave(1:dim)=0 DO i = 1.j))*(pos(3.j))*(pos(1.i)-v_ave(j))*(vel(j. psum !potential energy REAL*8 v_ave(dim) !average velocity of each dimension REAL*8 sumv2 !summation of velocity square REAL*8 radius !distance between two atoms REAL*8 force !force between two atoms INTEGER i.i)-v_ave(j)) END DO END DO temp1 = sumv2/REAL(num)/3.i)-pos(1.i)-pos(1.j)) .j)) + (pos(2.dim sumv2 = sumv2 + (vel(j.i)pos(2.num DO j = 1.i)-pos(2.num radius = (pos(1. pzz !current pressure REAL*8 etot !total energy of the system REAL*8 potential(num).rho) !measure system properties USE constants IMPLICIT NONE REAL*8 rho.num DO j = i+1.

0/(3.GE.0/(9.1415926*rho*(2.0 rsq=v1*v1+v2*v2 IF (rsq .0*3.j))*force pyy = pyy + (pos(2.ucor.0/vol RETURN END SUBROUTINE measure !----------------------------------------------------------------!----------------------------------------------------------------SUBROUTINE long_range_correction(rho.0*3.0) GOTO 100 rangauss=v1*SQRT(-2.0/(3.0 .j))*force END DO END DO pressure = rho*temp1+(pxx+pyy+pzz)/3.1415926*rho*(1. rsq .0 CALL RANDOM_NUMBER(v2) v2=2.0*v1-1.pcor) USE constants IMPLICIT NONE !calculate the long range corrections for potential energy and pressure REAL*8 rho !numdensity of the simulation REAL*8 ucor !long range correction for potential energy REAL*8 pcor !long range correction for pressure ucor = 8.0*LOG(rsq)/rsq) RETURN END !------------------------------------------------------------------------------ .0*rcut**3)) RETURN END SUBROUTINE long_range_correction !----------------------------------------------------------------!----------------------------------------------------------------FUNCTION rangauss() ! !To generate random numbers from a gaussian distribution.0*v2-1. ! REAL*8 ran_uniform.0/(radius**4)*(12/(radius**3)-6) pxx = pxx + (pos(1.j))*(pos(3.0*rcut**3)) pcor = 16.OR.0*rcut**9)-1. 0.0/(9.j))*(pos(2. 1.j))*(pos(1.j))*force pzz = pzz + (pos(3.LE. rsq 100 CALL RANDOM_NUMBER(v1) v1=2.i)-pos(1.i)-pos(1.force = 4.i)-pos(2. v1.i)-pos(3. v2.i)-pos(3. rangauss.0*rcut**9)-1.i)-pos(2.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->