#!/usr/bin/env python
# coding: utf-8
#
Energy versus Temperature
""" From "COMPUTATIONHL PHYSICS" & "COMPUTER PROBLEMS in PHYSICS"
by RH Landau, MJ Paez, and CC Bordeianu (deceased).
Copyright R Landau, Oregon State Unv, MJ Paez, Univ Antioquia,
C Bordeianu, Univ Bucharest, 2020.
Please respect copyright & acknowledge our work."""
# MoleDynam.py: molecular dynamics for 16 particles in a box
""" A Molecular Dynamics simulation of 16 particles in a box.
The particles interact via the Lennard Jones potential and thus the force:
$$
\mathbf{f} (r) = \frac{48}{r^2}
\left[\left( \frac{1}{r}\right)^{12} - \frac{1}{2}
\left(\frac{1}{r} \right)^6 \right] \mathbf{r}.
$$
The positions and velocities of the particles computed via
Verlet-velocity algorithm:
\begin{eqnarray}
\mathbf{r}_i(t+h) & \simeq & \mathbf{r}_i(t) + h \mathbf{v}_i(t) + \frac{h^2}
{2} \mathbf{F}_i(t) + \mbox{O}(h^3), \label{VV1}\\[6pt]
\mathbf{v}_i(t+h) & \simeq & \mathbf{v}_i(t) + h \,
\overline{\mathbf{a}(t)}+ \mbox{O}(h^2) \\[6pt]
& \simeq &\mathbf{v}_i(t) + h \left[ \frac{\mathbf{F}_i(t+h)+\mathbf{F}_i(t)}{2}
\right] + \mbox{O}(h^2). \label{VV2}
\end{eqnarray}
\item
The specific capacity at constant volume is:
$$
C_V= \frac{\partial E}{\partial T}\Bigr )_V
$$
The program calculates Energy vs temp and $C_v$"""
# In[1]:
from vpython import *
import numpy as np
import random
L=1 # side square
time=5
#scene = display(width=400,height=400,range=(1.3) )
scenetemp = graph(xmin=0,xmax=80.0,
width=400, height=400, xtitle='Temperature', ytitle='Total Energy',
ymax=50,ymin=0, title="Total Energy vs Temperature" )
plotT=gcurve(color=color.blue)
sceneEnergy=graph(x=400,xmin=0,xmax=80,ymax=1,ymin=0,
width=400, height=400, xtitle='Temperature', ytitle='Cv',
title="Heat capacity at constant Vol, vs T")
plotCv=gcurve(color=color.cyan)
plotPE=gcurve(color=color.magenta)
plotTE=gcurve(color=color.cyan)
Natom=16 # number of atoms
#Nr=0 # number particles right side
dt=1e-6 # time step
positions=[] # position of atoms
dN=[] # will contain atoms in right half at each tieme interval
fr=[0]*(Natom) # atoms (spheres)
fr2=[0]*(Natom) # second force
ar=0.03 # radius of atom # a reference velocity
h=0.02
factor=10**(-11.0) # for lennard jones
deltaN=1 # for histogram
Tem=[0]*(75)
KE=[0]*(75)
PtE=[0]*(75)
def initcond(pref): # initial conditions
Nr=0
vel=[]
global pos
for i in range (0,Natom): # initial positions and velocities
col=vec(1.3*random.random(),1.3*random.random(),1.3*random.random())
x=2.*(L-ar)*random.random()-L+ar #positons of atoms
y=2.*(L-ar)*random.random()-L+ar # in the border forbidden
theta=2*pi*random.random() # select angle 0<=theta<= 2pi
vx=pref*cos(theta) # x component velocity
vy=pref*sin(theta)
positions.append((x,y,0)) # add positions to list
vel.append((vx,vy,0)) # add momentum to list
posi=np.array(positions) # array with positions
ddp=posi[i]
if ddp[0]>=0 and ddp[0]<=L: # count initial atoms at right half
Nr+=1
v=np.array(vel) # array of velocities
return posi,v
def sign(a, b): # sign function
if (b >= 0.0):
return abs(a)
else:
return - abs(a)
def forces(fr):
fr=[0]*(Natom)
#PE=[0]*(Natom)
PE=0
for i in range( 0, Natom-1 ):
for j in range(i + 1, Natom):
dr=posi[i]-posi[j] # relative position between particles
if (abs(dr[0]) > L): # smallest distance from part.or image
dr[0] = dr[0] - sign(2*L, dr[0]) # interact with closer image
if (abs(dr[1]) > L): # same for y
dr[1] = dr[1] - sign(2*L, dr[1])
#r2=mag2(dr)
r2=dr[0]**2+dr[1]**2+dr[2]**2
if r2 < 0.02: # to avoid 0 denominator
r2 = 0.03 # minimum distance between 2 atoms
invr2 = 1./r2 # compute this factor
fij =invr2*factor* 48.*(invr2**3 - 0.5) *invr2**3 #
fr[i]=fij*dr+ fr[i]
fr[j]=-fij*dr +fr[j] # lennard jones force
PE = PE + factor* 4.*(invr2**3)*((invr2**3) - 1.)
return fr,PE
nn=0 # counter
for velo in arange(0.5,20,1.0):
#count=0
pref=velo
posi,v=initcond(pref)
for t in range (0,time): # time steps to make averages
Nr=0 # begin at zero in each time
v2=0
PE=0
for i in range(0,Natom):
fr,potE=forces(fr)
rate(500)
dpos=posi[i]
if dpos[0] <= -L:
posi[i] = [dpos[0]+2*L,dpos[1],0] # x periodic boundary conditions
if dpos[0] >= L:
posi[i] = [dpos[0]-2*L,dpos[1],0]
if dpos[1] <= -L:
posi[i] = [dpos[0],dpos[1]+2*L,0] # y periodic boundary conditions
if dpos[1] >= L:
posi[i] = [dpos[0],dpos[1]-2*L,0]
dpos=posi[i]
if dpos[0]>0 and dpos[0]1: # forward difference derivative to find: Cv=dE/dT
plotCv.plot(pos=(Tem[nn],(PtE[nn]+KE[nn]-PtE[nn-1]-KE[nn-1])/(Tem[nn]-Tem[nn-1])))
nn=nn+1
print("finished")