77.. Simulating simple fluidsSimulating simple fluidsphys.ubbcluj.ro/~tbeu/MD/C7.pdf · Allen, M....
Transcript of 77.. Simulating simple fluidsSimulating simple fluidsphys.ubbcluj.ro/~tbeu/MD/C7.pdf · Allen, M....
12/7/2011
1
Titus Beu 2011
Titus BeuUniversity “Babes-Bolyai”Department of Theoretical and Computational PhysicsCluj-Napoca, Romania
7. 7. Simulating simple fluidsSimulating simple fluids
Titus Beu 2011
Bibliography
Thermodynamic properties
Periodic boundary conditions
Initial configuration
Thermostats
Application
12/7/2011
2
Titus Beu 2011
Rapaport, D.C., The Art of Molecular Dynamics Simulation. Second Edition (Cambridge University Press, 2004).
Leach, A. R., Molecular Modelling. Principles and applications, Second edition (Prentice Hall, 2001) .
Frenkel , D., Smit, B., Understanding Molecular Simulation. From Algorithms to Applications (Academic Press, 2002).
Allen, M. P., Tildesley, D. J., Computer Simulation of Liquids (Clarendon Press, Oxford, 1991).
Sadus, R.J., Molecular Simulation of Fluids. Applications to Physical Systems, Second Edition (Elsevier, 1999).
Titus Beu 2011
System temperature – equipartition theorem → each degree of freedom kBT/2:
Pressure – virial formula:
For a pair potential:
Replacing T:
Etot = Ekin + Epot should be conserved throughout a simulation
T and P fluctuate – should be averaged over several time steps
B kin2
3
k ET
N=
B
1
1
3
N
i i
i
PV Nk T=
= + ⋅∑r F
B
1
3
N
ij ij
i j
PV Nk T<
= + ⋅∑r f
kin2
3
N
ij ij
i j
P EN
ρ
<
= + ⋅∑r f
12/7/2011
3
Titus Beu 2011
Macroscopic systems: N = 1021 −1023 particles (Avogadro’s number)
Typical bulk systems: N = 1021 → N2/3 = 1014 (1 in 107) surface particles
Tractable simulations: N = 106 → N2/3 = 104 (1 in 102) surface particles
Behaviour of "small" systems is dominated by surface effects
Minimizing surface effects for bulk systems:
Finite simulation box + Periodic Boundary Conditions (PBC)
The system is bounded, but free of physical walls
Enables simulations using a relatively small number of representative particleswhich experience forces as if they were in bulk fluid
The simplest simulation box – cubic [−L, L] × [−L, L] × [−L, L]
Limitation of PBC caused by the suppression of fluctuations with λ > L:
Not possible to simulate liquid-gas critical points – fluctuations are macroscopic
First order transitions appear to be of higher order
Titus Beu 2011
Simulation box
Defined to contain a manageable number of particles
Eliminate surface effects – space-filling array of identical copies of the simulation box
Real and “image” particles move synchronously
Aspects to be tackled:
Correcting the coordinates of the particles leaving the simulation box to conserve their total number
Reducing the no. of interactions(theoretically infinite) – minimum image criterion
Simulation box
−L L
−L
L
12/7/2011
4
Titus Beu 2011
Correcting particle coordinates
Should a particle leave the box, an image particle enters through the opposite boundary
The entering particle is identified with the exiting one – replaces it with corrected coordinates
Correction of position:
if x < −L then x’ = x + 2L
if x > +L then x’ = x − 2L
L – half-size of simulation box
Equivalently:
If |x| > L then x’ = x − sign(L,x)
Similar conditions along y and z
Simulation box
−L L
−L
L
Titus Beu 2011
Reducing the number of interactions
A short-range potential can be
characterized by a cut-off distance Rcut
For interatomic distances rij > Rcut
interactions can be neglected
For a box half-size L > Rcut any particle ilies within Rcut with at most one of all periodic images of particle j
Minimum image criterion – for a given particle interactions are to be considered only with the closest instances of all other particles
Correction of interatomic distance:
if xij < −L then xij’ = xij + 2L
if xij > +L then xij’ = xij − 2L
Tremendous CPU economy
−L L > Rcut
−L
L
Rcut
12/7/2011
5
Titus Beu 2011
//===========================================================================
void ForcesL(int iopRun, float epsilon, float sigma, float rcut, float Lbox,float x[], float y[], float z[],
float Fx[], float Fy[], float Fz[], int natm,float &Epot, float &virial)
//---------------------------------------------------------------------------// Returns forces for the Lennard-Jones 12-6 potential
// Energies in eV, forces in eV/Angs, distances in Angs{
float factE, factF, rcut2, sigma2;float dx, dy, dz, sr2, sr6, fpr, fxi, fyi, fzi, r2, Lbox2;
int iatm, jatm;
if (iopRun == 2) {Lbox2 = 2.e0 * Lbox; // total box size
rcut = min(rcut,Lbox);}
factE = 4.e0 * epsilon; factF = 48.e0 * epsilon;sigma2 = sigma * sigma; rcut2 = rcut * rcut;
Epot = 0.e0;
for (iatm=1; iatm<=natm; iatm++) Fx[iatm] = Fy[iatm] = Fz[iatm] = 0.e0;
//===========================================================================
void ForcesL(int iopRun, float epsilon, float sigma, float rcut, float Lbox,float x[], float y[], float z[],
float Fx[], float Fy[], float Fz[], int natm,float &Epot, float &virial)
//---------------------------------------------------------------------------// Returns forces for the Lennard-Jones 12-6 potential
// Energies in eV, forces in eV/Angs, distances in Angs{
float factE, factF, rcut2, sigma2;float dx, dy, dz, sr2, sr6, fpr, fxi, fyi, fzi, r2, Lbox2;
int iatm, jatm;
if (iopRun == 2) {Lbox2 = 2.e0 * Lbox; // total box size
rcut = min(rcut,Lbox);}
factE = 4.e0 * epsilon; factF = 48.e0 * epsilon;sigma2 = sigma * sigma; rcut2 = rcut * rcut;
Epot = 0.e0;
for (iatm=1; iatm<=natm; iatm++) Fx[iatm] = Fy[iatm] = Fz[iatm] = 0.e0;
Titus Beu 2011
for (iatm=1; iatm<=natm-1; iatm++) {
for (jatm=iatm+1; jatm<=natm; jatm++) {dx = x[iatm] - x[jatm];
dy = y[iatm] - y[jatm];dz = z[iatm] - z[jatm];
if (iopRun == 2) { // minimum image criterion
if (dx > Lbox) dx -= Lbox2; else if (dx < -Lbox) dx += Lbox2;if (dy > Lbox) dy -= Lbox2; else if (dy < -Lbox) dy += Lbox2;
if (dz > Lbox) dz -= Lbox2; else if (dz < -Lbox) dz += Lbox2;}
r2 = dx*dx + dy*dy + dz*dz;if (r2 < rcut2) {
sr2 = sigma2 / r2;sr6 = sr2 * sr2 * sr2;
fpr = factF * sr6 * (sr6 - 0.5e0) / r2; // f/r
fxi = fpr * dx;fyi = fpr * dy;
fzi = fpr * dz;Fx[iatm] += fxi; Fx[jatm] -= fxi;
Fy[iatm] += fyi; Fy[jatm] -= fyi;Fz[iatm] += fzi; Fz[jatm] -= fzi;
Epot += factE * sr6 * (sr6 - 1.e0);
virial += fpr * r2;}
}}
if (iopRun == 2) { Epot /= natm; virial /= natm; }}
for (iatm=1; iatm<=natm-1; iatm++) {
for (jatm=iatm+1; jatm<=natm; jatm++) {dx = x[iatm] - x[jatm];
dy = y[iatm] - y[jatm];dz = z[iatm] - z[jatm];
if (iopRun == 2) { // minimum image criterion
if (dx > Lbox) dx -= Lbox2; else if (dx < -Lbox) dx += Lbox2;if (dy > Lbox) dy -= Lbox2; else if (dy < -Lbox) dy += Lbox2;
if (dz > Lbox) dz -= Lbox2; else if (dz < -Lbox) dz += Lbox2;}
r2 = dx*dx + dy*dy + dz*dz;if (r2 < rcut2) {
sr2 = sigma2 / r2;sr6 = sr2 * sr2 * sr2;
fpr = factF * sr6 * (sr6 - 0.5e0) / r2; // f/r
fxi = fpr * dx;fyi = fpr * dy;
fzi = fpr * dz;Fx[iatm] += fxi; Fx[jatm] -= fxi;
Fy[iatm] += fyi; Fy[jatm] -= fyi;Fz[iatm] += fzi; Fz[jatm] -= fzi;
Epot += factE * sr6 * (sr6 - 1.e0);
virial += fpr * r2;}
}}
if (iopRun == 2) { Epot /= natm; virial /= natm; }}
12/7/2011
6
Titus Beu 2011
//===========================================================================
void ForcesB(int iopRun, float kfor, float req, float rcut, float Lbox,float x[], float y[], float z[],
float Fx[], float Fy[], float Fz[], int natm,float &Epot, float &virial)
//---------------------------------------------------------------------------// Returns harmonic forces for bonded interactions
// Energies in eV, forces in eV/Angs, distances in Angs{
float factE, factF, Ecut;float dr, dx, dy, dz, fpr, fxi, fyi, fzi, r, Lbox2;
int iatm, jatm;
if (iopRun == 2) {Lbox2 = 2.e0 * Lbox; // total box size
rcut = min(rcut,Lbox);}
factE = 0.5e0 * kfor;factF = -kfor;
dr = rcut - req;Ecut = factE * dr * dr; // E(rcut)
Epot = 0.e0;
for (iatm=1; iatm<=natm; iatm++) Fx[iatm] = Fy[iatm] = Fz[iatm] = 0.e0;
//===========================================================================
void ForcesB(int iopRun, float kfor, float req, float rcut, float Lbox,float x[], float y[], float z[],
float Fx[], float Fy[], float Fz[], int natm,float &Epot, float &virial)
//---------------------------------------------------------------------------// Returns harmonic forces for bonded interactions
// Energies in eV, forces in eV/Angs, distances in Angs{
float factE, factF, Ecut;float dr, dx, dy, dz, fpr, fxi, fyi, fzi, r, Lbox2;
int iatm, jatm;
if (iopRun == 2) {Lbox2 = 2.e0 * Lbox; // total box size
rcut = min(rcut,Lbox);}
factE = 0.5e0 * kfor;factF = -kfor;
dr = rcut - req;Ecut = factE * dr * dr; // E(rcut)
Epot = 0.e0;
for (iatm=1; iatm<=natm; iatm++) Fx[iatm] = Fy[iatm] = Fz[iatm] = 0.e0;
Titus Beu 2011
for (iatm=1; iatm<=natm-1; iatm++) {
for (jatm=iatm+1; jatm<=natm; jatm++) {dx = x[iatm] - x[jatm];
dy = y[iatm] - y[jatm];dz = z[iatm] - z[jatm];
if (iopRun == 2) { // minimum image criterion
if (dx > Lbox) dx -= Lbox2; else if (dx < -Lbox) dx += Lbox2;if (dy > Lbox) dy -= Lbox2; else if (dy < -Lbox) dy += Lbox2;
if (dz > Lbox) dz -= Lbox2; else if (dz < -Lbox) dz += Lbox2;}
r = sqrt(dx*dx + dy*dy + dz*dz);
if (r <= rcut) {dr = r - req;
fpr = factF * dr / r; // f/rfxi = fpr * dx;
fyi = fpr * dy;fzi = fpr * dz;
Fx[iatm] += fxi; Fx[jatm] -= fxi;Fy[iatm] += fyi; Fy[jatm] -= fyi;
Fz[iatm] += fzi; Fz[jatm] -= fzi;
Epot += factE * dr * dr - Ecut;virial += factF * dr * r;
}}
}
if (iopRun == 2) { Epot /= natm; virial /= natm; }}
for (iatm=1; iatm<=natm-1; iatm++) {
for (jatm=iatm+1; jatm<=natm; jatm++) {dx = x[iatm] - x[jatm];
dy = y[iatm] - y[jatm];dz = z[iatm] - z[jatm];
if (iopRun == 2) { // minimum image criterion
if (dx > Lbox) dx -= Lbox2; else if (dx < -Lbox) dx += Lbox2;if (dy > Lbox) dy -= Lbox2; else if (dy < -Lbox) dy += Lbox2;
if (dz > Lbox) dz -= Lbox2; else if (dz < -Lbox) dz += Lbox2;}
r = sqrt(dx*dx + dy*dy + dz*dz);
if (r <= rcut) {dr = r - req;
fpr = factF * dr / r; // f/rfxi = fpr * dx;
fyi = fpr * dy;fzi = fpr * dz;
Fx[iatm] += fxi; Fx[jatm] -= fxi;Fy[iatm] += fyi; Fy[jatm] -= fyi;
Fz[iatm] += fzi; Fz[jatm] -= fzi;
Epot += factE * dr * dr - Ecut;virial += factF * dr * r;
}}
}
if (iopRun == 2) { Epot /= natm; virial /= natm; }}
12/7/2011
7
Titus Beu 2011
//===========================================================================
void Verlet(int iopRun, float amass, float fpar, float rpar, float rcut,float Lbox, float dt,
float x[], float y[], float z[],float vx[], float vy[], float vz[],
float ax[], float ay[], float az[], int natm,float &Ekin, float &Epot, float &virial, int fopt)
//---------------------------------------------------------------------------// x[Angs], v[Angs/psec], a[Angs/psec*psec], F[eV/Angs], E[eV]
{float dt2;
int iatm;
dt2 = 0.5e0 * dt;for (iatm=1; iatm<=natm; iatm++) {
vx[iatm] += ax[iatm] * dt2; // v(t+dt/2)vy[iatm] += ay[iatm] * dt2;
vz[iatm] += az[iatm] * dt2;x[iatm] += vx[iatm] * dt; // r(t+dt)
y[iatm] += vy[iatm] * dt;z[iatm] += vz[iatm] * dt;
}
switch(fopt) { // F(t+dt)case 0:
ForcesL(iopRun,fpar,rpar,rcut,Lbox,x,y,z,ax,ay,az,natm,Epot,virial);break;
case 1:ForcesB(iopRun,fpar,rpar,rcut,Lbox,x,y,z,ax,ay,az,natm,Epot,virial);
}
//===========================================================================
void Verlet(int iopRun, float amass, float fpar, float rpar, float rcut,float Lbox, float dt,
float x[], float y[], float z[],float vx[], float vy[], float vz[],
float ax[], float ay[], float az[], int natm,float &Ekin, float &Epot, float &virial, int fopt)
//---------------------------------------------------------------------------// x[Angs], v[Angs/psec], a[Angs/psec*psec], F[eV/Angs], E[eV]
{float dt2;
int iatm;
dt2 = 0.5e0 * dt;for (iatm=1; iatm<=natm; iatm++) {
vx[iatm] += ax[iatm] * dt2; // v(t+dt/2)vy[iatm] += ay[iatm] * dt2;
vz[iatm] += az[iatm] * dt2;x[iatm] += vx[iatm] * dt; // r(t+dt)
y[iatm] += vy[iatm] * dt;z[iatm] += vz[iatm] * dt;
}
switch(fopt) { // F(t+dt)case 0:
ForcesL(iopRun,fpar,rpar,rcut,Lbox,x,y,z,ax,ay,az,natm,Epot,virial);break;
case 1:ForcesB(iopRun,fpar,rpar,rcut,Lbox,x,y,z,ax,ay,az,natm,Epot,virial);
}
Titus Beu 2011
Ekin = 0.e0;
for (iatm=1; iatm<=natm; iatm++) {ax[iatm] /= amass; // a(t+dt)
ay[iatm] /= amass;az[iatm] /= amass;
vx[iatm] += ax[iatm] * dt2; // v(t+dt)vy[iatm] += ay[iatm] * dt2;
vz[iatm] += az[iatm] * dt2;Ekin += vx[iatm]*vx[iatm] + vy[iatm]*vy[iatm] + vz[iatm]*vz[iatm];
}Ekin *= 0.5e0 * amass;
if (iopRun == 2) Ekin /= natm;
}
Ekin = 0.e0;
for (iatm=1; iatm<=natm; iatm++) {ax[iatm] /= amass; // a(t+dt)
ay[iatm] /= amass;az[iatm] /= amass;
vx[iatm] += ax[iatm] * dt2; // v(t+dt)vy[iatm] += ay[iatm] * dt2;
vz[iatm] += az[iatm] * dt2;Ekin += vx[iatm]*vx[iatm] + vy[iatm]*vy[iatm] + vz[iatm]*vz[iatm];
}Ekin *= 0.5e0 * amass;
if (iopRun == 2) Ekin /= natm;
}
12/7/2011
8
Titus Beu 2011
//===========================================================================
void BoundCond0(float Lbox, float x[], float y[], float z[], int natm)//---------------------------------------------------------------------------
// Adjusts the atomic coordinates for periodic boundary conditions//---------------------------------------------------------------------------
{float Lbox2;
int iatm;
Lbox2 = 2.e0 * Lbox; // total box sizefor (iatm=1; iatm<=natm; iatm++) {
if (x[iatm] > Lbox) x[iatm] -= Lbox2; elseif (x[iatm] < -Lbox) x[iatm] += Lbox2;
if (y[iatm] > Lbox) y[iatm] -= Lbox2; elseif (y[iatm] < -Lbox) y[iatm] += Lbox2;
if (z[iatm] > Lbox) z[iatm] -= Lbox2; elseif (z[iatm] < -Lbox) z[iatm] += Lbox2;
}}
//===========================================================================
void BoundCond0(float Lbox, float x[], float y[], float z[], int natm)//---------------------------------------------------------------------------
// Adjusts the atomic coordinates for periodic boundary conditions//---------------------------------------------------------------------------
{float Lbox2;
int iatm;
Lbox2 = 2.e0 * Lbox; // total box sizefor (iatm=1; iatm<=natm; iatm++) {
if (x[iatm] > Lbox) x[iatm] -= Lbox2; elseif (x[iatm] < -Lbox) x[iatm] += Lbox2;
if (y[iatm] > Lbox) y[iatm] -= Lbox2; elseif (y[iatm] < -Lbox) y[iatm] += Lbox2;
if (z[iatm] > Lbox) z[iatm] -= Lbox2; elseif (z[iatm] < -Lbox) z[iatm] += Lbox2;
}}
Titus Beu 2011
//===========================================================================
void BoundCond(float Lbox, float x[], float y[], float z[], float xPBC[], float yPBC[], float zPBC[], int natm)
//---------------------------------------------------------------------------// Adjusts the atomic coordinates for periodic boundary conditions.
// Stores the total PBC corrections in xPBC[iatm], yPBC[iatm] and zPBC[iatm]// to be used in computing diffusion coefficients.
//---------------------------------------------------------------------------{
float Lbox2;int iatm;
Lbox2 = 2.e0 * Lbox; // total box size
for (iatm=1; iatm<=natm; iatm++) {if (x[iatm] > Lbox) { x[iatm] -= Lbox2; xPBC[iatm] -= Lbox2; } else
if (x[iatm] < -Lbox) { x[iatm] += Lbox2; xPBC[iatm] += Lbox2; }if (y[iatm] > Lbox) { y[iatm] -= Lbox2; yPBC[iatm] -= Lbox2; } else
if (y[iatm] < -Lbox) { y[iatm] += Lbox2; yPBC[iatm] += Lbox2; }if (z[iatm] > Lbox) { z[iatm] -= Lbox2; zPBC[iatm] -= Lbox2; } else
if (z[iatm] < -Lbox) { z[iatm] += Lbox2; zPBC[iatm] += Lbox2; }}
}
//===========================================================================
void BoundCond(float Lbox, float x[], float y[], float z[], float xPBC[], float yPBC[], float zPBC[], int natm)
//---------------------------------------------------------------------------// Adjusts the atomic coordinates for periodic boundary conditions.
// Stores the total PBC corrections in xPBC[iatm], yPBC[iatm] and zPBC[iatm]// to be used in computing diffusion coefficients.
//---------------------------------------------------------------------------{
float Lbox2;int iatm;
Lbox2 = 2.e0 * Lbox; // total box size
for (iatm=1; iatm<=natm; iatm++) {if (x[iatm] > Lbox) { x[iatm] -= Lbox2; xPBC[iatm] -= Lbox2; } else
if (x[iatm] < -Lbox) { x[iatm] += Lbox2; xPBC[iatm] += Lbox2; }if (y[iatm] > Lbox) { y[iatm] -= Lbox2; yPBC[iatm] -= Lbox2; } else
if (y[iatm] < -Lbox) { y[iatm] += Lbox2; yPBC[iatm] += Lbox2; }if (z[iatm] > Lbox) { z[iatm] -= Lbox2; zPBC[iatm] -= Lbox2; } else
if (z[iatm] < -Lbox) { z[iatm] += Lbox2; zPBC[iatm] += Lbox2; }}
}
12/7/2011
9
Titus Beu 2011
Initial configuration in NVE and NVT simulations needs to:
be homogeneous (not necessarily random)
satisfy a given density
Simple choice – regular arrangement on rectangular mesh – density easy to control
Volume of simulation box for N particles of mass m and density ρ: V = Nm/ρ
Half-size of cubic box centred at the origin: L = V1/3/2
N = n1/3 particles → cubic grid with n equidistant nodes in each direction (h = 2L/n):
xi = −L + (i − 1/2)h, i = 1,n
yj = −L + (j − 1/2)h, j = 1,n
zk = −L + (k − 1/2)h, k = 1,n
Each particle can be assigned a randomly oriented velocity of equal absolute value:
B3v k T m=
Titus Beu 2011
//===========================================================================
void InitFluid(int iopInit, char aname[2], float amass,float dens, float Temp, float &Lbox,
float x[], float y[], float z[],float vx[], float vy[], float vz[],
float ax[], float ay[], float az[], int natm)//---------------------------------------------------------------------------
// Arranges atoms on a cubic grid (natm**(1/3) atoms along each direction)// and assigns them randomly oriented velocities corresponding to Temp.
// Simulation box: [-Lbox,Lbox] x [-Lbox,Lbox] x [-Lbox,Lbox]//---------------------------------------------------------------------------
{float Ekin, h, Vbox, xi, yj, zk;
int i, iatm, j, k, ngrid;
ngrid = Nint(pow(natm,(1.e0/3.e0))); // total no. of atoms must be a cubeif (Nint(pow(ngrid,3)) != natm) {
printf("InitFluid: pow(ngrid,3) != natm\n");getch(); exit(1);
}
Vbox = natm * amass / dens; // simulation box volumeLbox = 0.5e0 * pow(Vbox,(1.e0/3.e0)); // simulation box half-size
//===========================================================================
void InitFluid(int iopInit, char aname[2], float amass,float dens, float Temp, float &Lbox,
float x[], float y[], float z[],float vx[], float vy[], float vz[],
float ax[], float ay[], float az[], int natm)//---------------------------------------------------------------------------
// Arranges atoms on a cubic grid (natm**(1/3) atoms along each direction)// and assigns them randomly oriented velocities corresponding to Temp.
// Simulation box: [-Lbox,Lbox] x [-Lbox,Lbox] x [-Lbox,Lbox]//---------------------------------------------------------------------------
{float Ekin, h, Vbox, xi, yj, zk;
int i, iatm, j, k, ngrid;
ngrid = Nint(pow(natm,(1.e0/3.e0))); // total no. of atoms must be a cubeif (Nint(pow(ngrid,3)) != natm) {
printf("InitFluid: pow(ngrid,3) != natm\n");getch(); exit(1);
}
Vbox = natm * amass / dens; // simulation box volumeLbox = 0.5e0 * pow(Vbox,(1.e0/3.e0)); // simulation box half-size
12/7/2011
10
Titus Beu 2011
h = 2.e0 * Lbox / ngrid;
iatm = 0;for (i=1; i<=ngrid; i++) {
xi = -Lbox + (i - 0.5) * h;for (j=1; j<=ngrid; j++) {
yj = -Lbox + (j - 0.5) * h;for (k=1; k<=ngrid; k++) {
zk = -Lbox + (k - 0.5) * h;iatm = iatm + 1;
x[iatm] = xi; y[iatm] = yj; z[iatm] = zk;}
}}
Ekin = 1.5e0 * natm * Temp;
Heat(amass,vx,vy,vz,natm,Ekin);for (iatm=1; iatm<=natm; iatm++) ax[iatm] = ay[iatm] = az[iatm] = 0.e0;
}
h = 2.e0 * Lbox / ngrid;
iatm = 0;for (i=1; i<=ngrid; i++) {
xi = -Lbox + (i - 0.5) * h;for (j=1; j<=ngrid; j++) {
yj = -Lbox + (j - 0.5) * h;for (k=1; k<=ngrid; k++) {
zk = -Lbox + (k - 0.5) * h;iatm = iatm + 1;
x[iatm] = xi; y[iatm] = yj; z[iatm] = zk;}
}}
Ekin = 1.5e0 * natm * Temp;
Heat(amass,vx,vy,vz,natm,Ekin);for (iatm=1; iatm<=natm; iatm++) ax[iatm] = ay[iatm] = az[iatm] = 0.e0;
}
Titus Beu 2011
Microcanonical (NVE) ensemble does not correspond to the conditions under which most experiments are carried out
Canonical NVT ensemble – system in contact with a heat bath (T0 = const)
Advantage: avoid energy drifts caused by the accumulation of numerical errors
Simple velocity scaling (T0 – desired temperature):
Berendsen thermostat (τ – coupling constant):
2
kin
B
0 kin
1
3
,
i
i
i i
T mvNk
T T v vλ λ
=
′= =
∑
( )0
0
kin
1
1 1
dTT T
dt
Tt
T
τ
δλ
τ
= −
= + −
12/7/2011
11
Titus Beu 2011
//===========================================================================
void Thermostat(float vx[], float vy[], float vz[], int natm,float Temp, float tau, float dt, float &Ekin)
//---------------------------------------------------------------------------// Rescales the velocities and total kinetic energy according to the
// Berendsen thermostat{
float f, Tkin;int iatm;
Tkin = Ekin/1.5e0;
f = sqrt(1.e0 + (dt/tau)*(Temp/Tkin - 1.e0)); // scaling factorfor (iatm=1; iatm<=natm; iatm++) {
vx[iatm] *= f;vy[iatm] *= f;
vz[iatm] *= f;}
Ekin *= f*f;}
//===========================================================================
void Thermostat(float vx[], float vy[], float vz[], int natm,float Temp, float tau, float dt, float &Ekin)
//---------------------------------------------------------------------------// Rescales the velocities and total kinetic energy according to the
// Berendsen thermostat{
float f, Tkin;int iatm;
Tkin = Ekin/1.5e0;
f = sqrt(1.e0 + (dt/tau)*(Temp/Tkin - 1.e0)); // scaling factorfor (iatm=1; iatm<=natm; iatm++) {
vx[iatm] *= f;vy[iatm] *= f;
vz[iatm] *= f;}
Ekin *= f*f;}
Titus Beu 2011
System in contact with a heat bath (T = const)
Gauss’s principle of least constraint: for the constrained motion
The motion is no longer Newtonian
Constrained equations of motion of the molecules:
Lagrange multipliers:
2( / ) mini i i i
i
m m− =∑ a F
Newton/ ,i i i i i i i
m α β= + = +a F v q q q�� �� �
2 2
, ,,
,i i i ii i
i i i x i xi i xm I
α βω
⋅ ⋅= − = −∑ ∑∑ ∑
v F ω M
v
12/7/2011
12
Titus Beu 2011
//---------------------------------------------------------------------------
//----------------------------------- MD ------------------------------------//---------------------------------------------------------------------------
#include <winbgim.h>#include "Memalloc.h"
#include "Graphlib.h"#include "Random.h"
#include "Utils.h"#include "Units.h"
#include "Rescal.h"#include "Inout.h"
#include "DataAtom.h"#include "InitConfig.h"
#include "Forces.h"#include "Propag.h"
#include "BoundCond.h"#include "Measure.h"
#include "Spectrum.h"#include "PlotCfg.h"
#include "Plots.h"//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//----------------------------------- MD ------------------------------------//---------------------------------------------------------------------------
#include <winbgim.h>#include "Memalloc.h"
#include "Graphlib.h"#include "Random.h"
#include "Utils.h"#include "Units.h"
#include "Rescal.h"#include "Inout.h"
#include "DataAtom.h"#include "InitConfig.h"
#include "Forces.h"#include "Propag.h"
#include "BoundCond.h"#include "Measure.h"
#include "Spectrum.h"#include "PlotCfg.h"
#include "Plots.h"//---------------------------------------------------------------------------
Titus Beu 2011
int main()
{char aname[2];
float *x, *y, *z, *vx, *vy, *vz, *vx0, *vy0, *vz0, *ax, *ay, *az;float *Ekin, *Etot, *Pres, *Bmin, *Bmax, *dbond;
float *CorVel, *Intens, *freq;float *Hfunc, *Diff;
float *rHist, *frHist;float *vHist, *fvHist;
float *xPBC, *yPBC, *zPBC;int *atom1, *atom2;
float amass, fpar, rpar, rbnd, rcut, dens, Temp, Lbox, dt, dtOut;float Ekini, EkinAvg, EkinSig, Epoti, EtotAvg, EtotSig;
float Presi, PresAvg, PresSig, virial, t;float BondMin, BondMax, freqMin, freqMax;
float fact, rHistMax, vHistMax;int iatm, iopRun, iopInit, isave, istep, maxbond, fopt;
int natm, nbond, nfreq, nsave, nstep, nstepOut;int nrHist, nvHist, nsum_stat, nsum_rHist, nsum_vHist, nsum_Diff;
int CPUtime, CPUtime0;
int main()
{char aname[2];
float *x, *y, *z, *vx, *vy, *vz, *vx0, *vy0, *vz0, *ax, *ay, *az;float *Ekin, *Etot, *Pres, *Bmin, *Bmax, *dbond;
float *CorVel, *Intens, *freq;float *Hfunc, *Diff;
float *rHist, *frHist;float *vHist, *fvHist;
float *xPBC, *yPBC, *zPBC;int *atom1, *atom2;
float amass, fpar, rpar, rbnd, rcut, dens, Temp, Lbox, dt, dtOut;float Ekini, EkinAvg, EkinSig, Epoti, EtotAvg, EtotSig;
float Presi, PresAvg, PresSig, virial, t;float BondMin, BondMax, freqMin, freqMax;
float fact, rHistMax, vHistMax;int iatm, iopRun, iopInit, isave, istep, maxbond, fopt;
int natm, nbond, nfreq, nsave, nstep, nstepOut;int nrHist, nvHist, nsum_stat, nsum_rHist, nsum_vHist, nsum_Diff;
int CPUtime, CPUtime0;
12/7/2011
13
Titus Beu 2011
initwindow(1100,700);
Input(iopRun,iopInit,aname,dens,Temp,dt,natm,nstep,nstepOut);
DataAtom(aname,amass,fpar,rpar,rbnd,rcut,fopt);
dtOut = dt * nstepOut;
nsave = nstep / nstepOut;nstep = nsave * nstepOut;
maxbond = natm*(natm-1)/2; // max. no. of bondsnrHist = 100; rHistMax = 20.e0;
nvHist = 100; vHistMax = 3.e0 * sqrt(3.e0*Temp / amass);
x = Vector(1,natm); y = Vector(1,natm); z = Vector(1,natm);vx = Vector(1,natm); vy = Vector(1,natm); vz = Vector(1,natm);
vx0 = Vector(1,natm); vy0 = Vector(1,natm); vz0 = Vector(1,natm);ax = Vector(1,natm); ay = Vector(1,natm); az = Vector(1,natm);
Ekin = Vector(1,nsave); Etot = Vector(1,nsave); Pres = Vector(1,nsave);dbond = Vector(1,maxbond); Bmin = Vector(1,nsave); Bmax = Vector(1,nsave);
CorVel = Vector(1,nsave); Intens = Vector(1,nsave); freq = Vector(1,nsave);Hfunc = Vector(1,nsave); Diff = Vector(1,nsave);
rHist = Vector(1,nrHist); frHist = Vector(1,nrHist);vHist = Vector(1,nvHist); fvHist = Vector(1,nvHist);
xPBC = Vector(1,natm); yPBC = Vector(1,natm); zPBC = Vector(1,natm);atom1 = IVector(1,maxbond); atom2 = IVector(1,maxbond);
Randomize();
initwindow(1100,700);
Input(iopRun,iopInit,aname,dens,Temp,dt,natm,nstep,nstepOut);
DataAtom(aname,amass,fpar,rpar,rbnd,rcut,fopt);
dtOut = dt * nstepOut;
nsave = nstep / nstepOut;nstep = nsave * nstepOut;
maxbond = natm*(natm-1)/2; // max. no. of bondsnrHist = 100; rHistMax = 20.e0;
nvHist = 100; vHistMax = 3.e0 * sqrt(3.e0*Temp / amass);
x = Vector(1,natm); y = Vector(1,natm); z = Vector(1,natm);vx = Vector(1,natm); vy = Vector(1,natm); vz = Vector(1,natm);
vx0 = Vector(1,natm); vy0 = Vector(1,natm); vz0 = Vector(1,natm);ax = Vector(1,natm); ay = Vector(1,natm); az = Vector(1,natm);
Ekin = Vector(1,nsave); Etot = Vector(1,nsave); Pres = Vector(1,nsave);dbond = Vector(1,maxbond); Bmin = Vector(1,nsave); Bmax = Vector(1,nsave);
CorVel = Vector(1,nsave); Intens = Vector(1,nsave); freq = Vector(1,nsave);Hfunc = Vector(1,nsave); Diff = Vector(1,nsave);
rHist = Vector(1,nrHist); frHist = Vector(1,nrHist);vHist = Vector(1,nvHist); fvHist = Vector(1,nvHist);
xPBC = Vector(1,natm); yPBC = Vector(1,natm); zPBC = Vector(1,natm);atom1 = IVector(1,maxbond); atom2 = IVector(1,maxbond);
Randomize();
Titus Beu 2011
switch (iopRun) { // initialize configuration
case 0:case 1:
InitClus(iopInit,aname,amass,rpar,Temp,x,y,z,vx,vy,vz,ax,ay,az,natm);
break;case 2:
InitFluid(iopInit,aname,amass,dens,Temp,Lbox,x,y,z,vx,vy,vz,ax,ay,az,natm);
if (Lbox < rcut) {printf("MD: Lbox < rcut !\n");
getch(); exit(1);}
rHistMax = min(rHistMax,Lbox);SavePDB(aname,x,y,z,natm);
}
Output0(iopRun,iopInit,aname,amass,fpar,rpar,rcut,dens,Lbox,Temp,dt,natm,nstep,nstepOut);
if (iopRun >= 1)
for (iatm=1; iatm<=natm; iatm++) {vx0[iatm] = vx[iatm]; vy0[iatm] = vy[iatm]; vz0[iatm] = vz[iatm];
xPBC[iatm] = yPBC[iatm] = zPBC[iatm] = 0.e0;}
switch (iopRun) { // initialize configuration
case 0:case 1:
InitClus(iopInit,aname,amass,rpar,Temp,x,y,z,vx,vy,vz,ax,ay,az,natm);
break;case 2:
InitFluid(iopInit,aname,amass,dens,Temp,Lbox,x,y,z,vx,vy,vz,ax,ay,az,natm);
if (Lbox < rcut) {printf("MD: Lbox < rcut !\n");
getch(); exit(1);}
rHistMax = min(rHistMax,Lbox);SavePDB(aname,x,y,z,natm);
}
Output0(iopRun,iopInit,aname,amass,fpar,rpar,rcut,dens,Lbox,Temp,dt,natm,nstep,nstepOut);
if (iopRun >= 1)
for (iatm=1; iatm<=natm; iatm++) {vx0[iatm] = vx[iatm]; vy0[iatm] = vy[iatm]; vz0[iatm] = vz[iatm];
xPBC[iatm] = yPBC[iatm] = zPBC[iatm] = 0.e0;}
12/7/2011
14
Titus Beu 2011
CPUtime0 = time(NULL);
t = 0.e0;
nsum_stat = 0;nsum_rHist = 0;
nsum_vHist = 0;nsum_Diff = 0;
for (istep=1; istep<=nstep; istep++) { // MAIN TEMPORAL LOOPt += dt;
Verlet(iopRun,amass,fpar,rpar,rcut,Lbox,dt,x,y,z,vx,vy,vz,ax,ay,az,natm,Ekini,Epoti,virial,fopt);
if (iopRun == 0) { // simmulated annealing
Ekini *= 0.99;Vrescal(amass,vx,vy,vz,natm,Ekini);
}
if (iopRun == 2) {BoundCond(Lbox,x,y,z,xPBC,yPBC,zPBC,natm); // periodic bound. cond.
Thermostat(vx,vy,vz,natm,Temp,10*dt,dt,Ekini);}
if (istep % nstepOut == 0) { // measurements & output
isave = istep / nstepOut;Ekin[isave] = Ekini;
Etot[isave] = Ekini + Epoti;
CPUtime0 = time(NULL);
t = 0.e0;
nsum_stat = 0;nsum_rHist = 0;
nsum_vHist = 0;nsum_Diff = 0;
for (istep=1; istep<=nstep; istep++) { // MAIN TEMPORAL LOOPt += dt;
Verlet(iopRun,amass,fpar,rpar,rcut,Lbox,dt,x,y,z,vx,vy,vz,ax,ay,az,natm,Ekini,Epoti,virial,fopt);
if (iopRun == 0) { // simmulated annealing
Ekini *= 0.99;Vrescal(amass,vx,vy,vz,natm,Ekini);
}
if (iopRun == 2) {BoundCond(Lbox,x,y,z,xPBC,yPBC,zPBC,natm); // periodic bound. cond.
Thermostat(vx,vy,vz,natm,Temp,10*dt,dt,Ekini);}
if (istep % nstepOut == 0) { // measurements & output
isave = istep / nstepOut;Ekin[isave] = Ekini;
Etot[isave] = Ekini + Epoti;
Titus Beu 2011
switch (iopRun) {
case 0: // cluster structureBonds(x,y,z,natm,atom1,atom2,dbond,nbond,rcut,
Bmin[isave],Bmax[isave]);break;
case 1: // cluster spectrumBonds(x,y,z,natm,atom1,atom2,dbond,nbond,rcut,
Bmin[isave],Bmax[isave]);CorVel[isave] = FuncCorr(isave-1,vx,vy,vz,natm);
freqMin = 0.e0; freqMax = 3.e3;Spectrum(CorVel,Intens,freq,freqMin,freqMax,dt*nstepOut,isave,nfreq);
break;case 2: // fluid structure
Presi = dens * (2.e0*Ekini + virial) / 3.e0;Statistics(Ekini,EkinAvg,EkinSig,Etot[isave],EtotAvg,EtotSig,
Presi,PresAvg,PresSig,nsum_stat);DistribV(vx,vy,vz,natm,vHist,fvHist,nvHist,vHistMax,nsum_vHist);
DistribR(Lbox,x,y,z,natm,rHist,frHist,nrHist,rHistMax,nsum_rHist);
Etot[isave] = EtotAvg;Pres[isave] = PresAvg;
Hfunc[isave] = HBoltzmann(vHist,fvHist,nvHist);Diff[isave] = DiffCorV(vx,vy,vz,natm,dt*nstepOut,nsum_Diff);
}
switch (iopRun) {
case 0: // cluster structureBonds(x,y,z,natm,atom1,atom2,dbond,nbond,rcut,
Bmin[isave],Bmax[isave]);break;
case 1: // cluster spectrumBonds(x,y,z,natm,atom1,atom2,dbond,nbond,rcut,
Bmin[isave],Bmax[isave]);CorVel[isave] = FuncCorr(isave-1,vx,vy,vz,natm);
freqMin = 0.e0; freqMax = 3.e3;Spectrum(CorVel,Intens,freq,freqMin,freqMax,dt*nstepOut,isave,nfreq);
break;case 2: // fluid structure
Presi = dens * (2.e0*Ekini + virial) / 3.e0;Statistics(Ekini,EkinAvg,EkinSig,Etot[isave],EtotAvg,EtotSig,
Presi,PresAvg,PresSig,nsum_stat);DistribV(vx,vy,vz,natm,vHist,fvHist,nvHist,vHistMax,nsum_vHist);
DistribR(Lbox,x,y,z,natm,rHist,frHist,nrHist,rHistMax,nsum_rHist);
Etot[isave] = EtotAvg;Pres[isave] = PresAvg;
Hfunc[isave] = HBoltzmann(vHist,fvHist,nvHist);Diff[isave] = DiffCorV(vx,vy,vz,natm,dt*nstepOut,nsum_Diff);
}
12/7/2011
15
Titus Beu 2011
cleardevice();
Output(iopRun,t,Ekin,Etot,Bmin,Bmax,Hfunc,Intens,freq,nsave,isave,nfreq,rHist,frHist,nrHist,vHist,fvHist,nvHist);
PlotCfg(iopRun,Lbox,x,y,atom1,atom2,natm,nbond,0.07e0,0.40e0,0.56e0,0.97e0);Plots(iopRun,Ekin,Etot,Pres,dbond,nbond,Bmin,Bmax,
CorVel,Intens,freq,dtOut,nsave,isave,nfreq,rHist,frHist,nrHist,vHist,fvHist,nvHist,
Hfunc,Diff);
if (iopRun == 0 && isave > 1) { // convergence checkif (fabs(1.e0 - Bmax[isave-1]/Bmax[isave]) <= 1.e-6) break;
}}
}
if (iopRun == 0) SavePDB(aname,x,y,z,natm); // save optimized structureCPUtime = time(NULL);
printf("\nCPU time: %5i sec\n",CPUtime-CPUtime0);getch();
}
cleardevice();
Output(iopRun,t,Ekin,Etot,Bmin,Bmax,Hfunc,Intens,freq,nsave,isave,nfreq,rHist,frHist,nrHist,vHist,fvHist,nvHist);
PlotCfg(iopRun,Lbox,x,y,atom1,atom2,natm,nbond,0.07e0,0.40e0,0.56e0,0.97e0);Plots(iopRun,Ekin,Etot,Pres,dbond,nbond,Bmin,Bmax,
CorVel,Intens,freq,dtOut,nsave,isave,nfreq,rHist,frHist,nrHist,vHist,fvHist,nvHist,
Hfunc,Diff);
if (iopRun == 0 && isave > 1) { // convergence checkif (fabs(1.e0 - Bmax[isave-1]/Bmax[isave]) <= 1.e-6) break;
}}
}
if (iopRun == 0) SavePDB(aname,x,y,z,natm); // save optimized structureCPUtime = time(NULL);
printf("\nCPU time: %5i sec\n",CPUtime-CPUtime0);getch();
}
Titus Beu 2011
2
0343
Ar300.
1.0e-4100000
10002.
2
0343
Ar300.
1.0e-4100000
10002.
md.dat:
Input:
fscanf(in,"%i",&iopRun); // run: 0,1,2 - structure, spectrum, fluid
fscanf(in,"%i",&iopInit); // initialization: 0-from file, 1-spherefscanf(in,"%i",&natm); // no. of atoms
fscanf(in,"%s",aname); // chemical symbolfscanf(in,"%f",&Temp); // kinetic temperature in K
fscanf(in,"%f",&dt); // integration time stepfscanf(in,"%i",&nstep); // no. of time steps
fscanf(in,"%i",&nstepOut); // no. of time steps for outputif (iopRun == 2) fscanf(in,"%f",&dens); // fluid density in g/cmc
fscanf(in,"%i",&iopRun); // run: 0,1,2 - structure, spectrum, fluid
fscanf(in,"%i",&iopInit); // initialization: 0-from file, 1-spherefscanf(in,"%i",&natm); // no. of atoms
fscanf(in,"%s",aname); // chemical symbolfscanf(in,"%f",&Temp); // kinetic temperature in K
fscanf(in,"%f",&dt); // integration time stepfscanf(in,"%i",&nstep); // no. of time steps
fscanf(in,"%i",&nstepOut); // no. of time steps for outputif (iopRun == 2) fscanf(in,"%f",&dens); // fluid density in g/cmc
12/7/2011
16
Titus Beu 2011
istep = 1
Titus Beu 2011
istep = 1000
12/7/2011
17
Titus Beu 2011
istep = 10000
Titus Beu 2011
istep = 100000