Hello everyone,
I am still testing MDA on a box filled with 512 TIP4P/2005 water molecules. positions are ouput every 1ps, the run last 200 ps. The density is converged = 0.996, RDF is OK.
I tried to plot the MSD vs time using the two msd classes :
MDAnalysis.analysis.msd.EinsteinMSD
and
MDAnalysis.analysis.waterdynamics.MeanSquareDisplacement
They gave me similar results.
import numpy as np
import MDAnalysis as mda
import MDAnalysis.analysis.msd as msd
dump ="wat_unwraped.lammpsdump"
lammpsData="wat.data"
u = mda.Universe(lammpsData,dump,dt=1,memory=True)
MSD = msd.EinsteinMSD(u, select='type 2', msd_type='xyz', fft=True)
MSD.run()
gives me a sel-diffusion coef = slope/(2*n) = 130.95 A²/ps
while it should be ~0.23 A²/ps
The MSD output by lammps gives me a correct D~0.22A²/ps
So I tried to calculate the MSD by hand :
O = u.select_atoms("type 2")
n_frames = u.trajectory.n_frames
n_at = O.n_atoms
# reference position at t=0
for ts in u.trajectory[0]:
ref=O.ts.positions
# displacement vector (dx, dy, dz) = (x,y,z) - (x0,y0,z0)
displacement = np.zeros(((n_frames),(n_at),3))
i = 0
for ts in u.trajectory:
displacement[i]=O.ts.positions - ref
i+=1
MSD=displacement*displacement # dx*dx, dy*dy, dz*dz
MSD=np.sum(MSD,axis=2) # dx² + dy² + dz²
MSD=np.mean(MSD,axis=1) # average over atoms
tf = n_frames
time = np.linspace(0, tf, n_frames)
fit = np.polyfit(time, MSD, 1)
y = np.poly1d(fit)
y_t = y(time)
fig, ax = plt.subplots()
plt.plot(time, MSD)
plt.plot(time, y_t)
ax.set_xlabel("time ns")
ax.set_ylabel("MSD A²")
print("diff coef = slope/(2*n) =", y[1]/6 )
which gives D = 130 A²/ps.
I have to admit that I am at loss...