You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
8.3 KiB
243 lines
8.3 KiB
2 years ago
|
#!/usr/bin/env python3
|
||
|
|
||
|
import sys
|
||
|
import numpy as np
|
||
|
from pymatgen.core import lattice, structure
|
||
|
import statsmodels.api as sm
|
||
|
import matplotlib
|
||
|
matplotlib.use('PS')
|
||
|
#matplotlib.rc('text', usetex=True)
|
||
|
#matplotlib.use('Qt5agg')
|
||
|
import matplotlib.pyplot as plt
|
||
|
|
||
|
def msd_com(groups,traject,start,latt,dt):
|
||
|
index_groups = []
|
||
|
|
||
|
entries = groups.split(':')
|
||
|
for entry in entries:
|
||
|
arr = entry.split('*')
|
||
|
if (len(arr) != 3):
|
||
|
print('Salah memasukkan format definisi molekul, pastikan dengan format Nama*JumlahAtom*JumlahMolekul')
|
||
|
parser.print_help()
|
||
|
sys.exit(1)
|
||
|
index_groups.append( (arr[0], int(arr[1]), int(arr[2])) )
|
||
|
# print(index_groups)
|
||
|
|
||
|
|
||
|
traj_file = traject
|
||
|
print('Titik acuan: ', start)
|
||
|
|
||
|
symbols = []
|
||
|
symbol_list = []
|
||
|
nat_list = []
|
||
|
cell = []
|
||
|
|
||
|
with open(latt, 'r') as f:
|
||
|
for line in f:
|
||
|
if 'TV' in line:
|
||
|
cell.append(list(map(float, line.split()[1:4])))
|
||
|
|
||
|
box = lattice.Lattice(cell)
|
||
|
|
||
|
#membaca geometri awal dari file trayektori dinamika molekul
|
||
|
with open(traj_file, 'r') as f:
|
||
|
nat = int(f.readline())
|
||
|
info = f.readline()
|
||
|
arr = info.split()
|
||
|
# t1 = float(arr[3])
|
||
|
for i in range(0, nat):
|
||
|
line = f.readline()
|
||
|
arr = line.split()
|
||
|
symbols.append(arr[0])
|
||
|
if (len(symbol_list) == 0):
|
||
|
symbol_list.append(arr[0])
|
||
|
nat_list.append(1)
|
||
|
else:
|
||
|
if (arr[0] == symbol_list[-1]):
|
||
|
nat_list[-1] += 1
|
||
|
else:
|
||
|
symbol_list.append(arr[0])
|
||
|
nat_list.append(1)
|
||
|
nat = int(f.readline())
|
||
|
info = f.readline()
|
||
|
arr = info.split()
|
||
|
# t2 = float(arr[3])
|
||
|
# dt = t2-t1
|
||
|
|
||
|
groups_nat = sum([k[1]*k[2] for k in index_groups])
|
||
|
if (groups_nat != nat):
|
||
|
raise ValueError('Salah dalam mendefinisikan molekul! Jumlah atom tidak konsisten.')
|
||
|
|
||
|
print('Kelompok:')
|
||
|
for k, nat, nmole in index_groups:
|
||
|
print (' Nama: {}, Jumlah atom dalam molekul: {}, Jumlah molekul dalam sistem: {}'. format(k, nat, nmole))
|
||
|
print("")
|
||
|
|
||
|
|
||
|
first = True
|
||
|
first_coords = []
|
||
|
|
||
|
|
||
|
def load_xyz(lattice, f):
|
||
|
nat = int(next(f))
|
||
|
title = next(f)
|
||
|
species = []
|
||
|
coords = []
|
||
|
for i in range(nat):
|
||
|
line = next(f)
|
||
|
arr = line.split()
|
||
|
species.append(arr[0])
|
||
|
coords.append(list(map(float, arr[1:4])))
|
||
|
mole = structure.Structure(lattice=lattice, species=species, coords=coords, coords_are_cartesian=True)
|
||
|
|
||
|
return mole
|
||
|
|
||
|
|
||
|
fout = open('msd.out', 'w')
|
||
|
format_str = '{:>15s}(A^2)'*len(index_groups)
|
||
|
|
||
|
print ('#Time(ps) ', format_str.format(*[k for k, nat, nmole in index_groups]), file=fout)
|
||
|
|
||
|
first_coms = None
|
||
|
last_coms = None
|
||
|
image_lasts = None
|
||
|
|
||
|
times = []
|
||
|
msds = []
|
||
|
|
||
|
with open(traj_file, 'r') as f:
|
||
|
step = 0
|
||
|
while(True):
|
||
|
try:
|
||
|
step += 1
|
||
|
|
||
|
struct = load_xyz(box, f)
|
||
|
atom_index = 0
|
||
|
group_index = 0
|
||
|
com_step = []
|
||
|
for group in index_groups:
|
||
|
# print('Menghitung pusat massa untuk molekul ke-{}'.format(group))
|
||
|
for mole_index in range(group[2]):
|
||
|
# print('Menghitung pusat massa untuk molekul ke-{}'.format (mole_index))
|
||
|
local_indexs = [atom_index + x for x in range(group[1])]
|
||
|
# print(local_indexs)
|
||
|
if (len(local_indexs) == 1):
|
||
|
com_step.append(struct.sites[local_indexs[0]].frac_coords)
|
||
|
else:
|
||
|
atom1 = struct[local_indexs[0]]
|
||
|
com_local = atom1.specie.data['Atomic mass']*atom1.frac_coords
|
||
|
total_mass = atom1.specie.data['Atomic mass']
|
||
|
for at2 in local_indexs[1:]:
|
||
|
atom2 = struct[at2]
|
||
|
dis_, image_ = atom1.distance_and_image(atom2)
|
||
|
com_local += atom2.specie.data['Atomic mass']*(atom2. frac_coords+image_)
|
||
|
total_mass += atom2.specie.data['Atomic mass']
|
||
|
com_local /= total_mass
|
||
|
com_step.append(com_local)
|
||
|
atom_index = local_indexs[-1]+1
|
||
|
|
||
|
if (step == 1):
|
||
|
first_coms = com_step.copy()
|
||
|
last_coms = com_step.copy()
|
||
|
image_lasts = [(0,0,0)]*len(last_coms)
|
||
|
else:
|
||
|
msd = []
|
||
|
image_cur_list = []
|
||
|
|
||
|
for first_com, last_com, cur_com, image_last in zip(first_coms, last_coms, com_step, image_lasts):
|
||
|
image_current = struct.lattice.get_distance_and_image(last_com, cur_com)[1]
|
||
|
image_final = image_last + image_current
|
||
|
final_dis = struct.lattice.get_distance_and_image(first_com, cur_com, jimage=image_final)[0]
|
||
|
msd.append(final_dis*final_dis)
|
||
|
image_cur_list.append(image_final)
|
||
|
|
||
|
image_lasts = image_cur_list
|
||
|
last_coms = com_step.copy()
|
||
|
|
||
|
msd_group = []
|
||
|
for i in range(len(index_groups)):
|
||
|
items = msd[0:index_groups[i][2]]
|
||
|
msd = msd[index_groups[i][2]:]
|
||
|
msd_group.append(sum(items)/len(items))
|
||
|
format_str = '{:<10.5f} ' + '{:20.12f}'*len(index_groups)
|
||
|
print (format_str.format(step*dt/1000.0, *msd_group), file=fout)
|
||
|
|
||
|
print('Tahap {} selesai'.format(step))
|
||
|
|
||
|
except StopIteration as e:
|
||
|
break
|
||
|
def msd_fit(msd,noheader,start):
|
||
|
data_file = msd
|
||
|
x = []
|
||
|
ys = []
|
||
|
ncol = -1
|
||
|
lineno = 0
|
||
|
headers = []
|
||
|
with open(data_file, 'r') as f:
|
||
|
for line in f:
|
||
|
lineno +=1
|
||
|
if (line.startswith('#')):
|
||
|
if noheader:
|
||
|
continue
|
||
|
if (lineno == 1):
|
||
|
headers = line.split()[1:]
|
||
|
continue
|
||
|
arr = line.split()
|
||
|
x.append(float(arr[0]))
|
||
|
ys.append(list(map(float, arr[1:])))
|
||
|
|
||
|
if (ncol == -1):
|
||
|
ncol = len(arr) -1
|
||
|
else:
|
||
|
if (ncol != (len(arr) -1)):
|
||
|
raise ValueError('The number of columns of data file is not consistent!')
|
||
|
|
||
|
|
||
|
print('Terdapat {} kolom dalam data MSD yang diberikan.'.format(ncol))
|
||
|
print()
|
||
|
|
||
|
print(headers)
|
||
|
if (len(headers) != ncol):
|
||
|
headers = []
|
||
|
for col in range(ncol):
|
||
|
headers.append('Kolom {}'.format(col+1))
|
||
|
|
||
|
for col in range(ncol):
|
||
|
print ('Kolom {}:'.format(col+1))
|
||
|
|
||
|
all_data_x = np.array(x, dtype=np.double).reshape(-1, 1)
|
||
|
data_x = all_data_x[start:-1]
|
||
|
|
||
|
all_data_y = [d[col] for d in ys]
|
||
|
data_y = np.array(all_data_y[start:-1], dtype=np.double).reshape(-1, 1)
|
||
|
X = sm.add_constant(data_x)
|
||
|
ols = sm.OLS(data_y, X)
|
||
|
ols_result = ols.fit()
|
||
|
|
||
|
summ = ols_result.summary()
|
||
|
# print(summ)
|
||
|
print('*'*80)
|
||
|
diff_coeff = ols_result.params[1]/6.0
|
||
|
print(' Koefisien Difusi = {:.2f} A^2/ps = {:.2e} m^2/s'.format (diff_coeff, diff_coeff*1.0e-8))
|
||
|
# diff_coeff = ols_result.params[1]/2.0
|
||
|
# print(' Diffusion coefficient (1/2): {:16.10F} A^2/ps, {:17.12E} m^2/s'.format (diff_coeff, diff_coeff*1.0e-8))
|
||
|
# diff_coeff = ols_result.params[1]/4.0
|
||
|
# print(' Diffusion coefficient (1/4): {:16.10F} A^2/ps, {:17.12E} m^2/s'.format (diff_coeff, diff_coeff*1.0e-8))
|
||
|
print('*'*80)
|
||
|
print()
|
||
|
|
||
|
predicted_y = ols_result.predict(X)
|
||
|
|
||
|
|
||
|
plt.plot(x, all_data_y, label=headers[col].strip('(A^2)'))
|
||
|
plt.plot(data_x, predicted_y, 'k--')
|
||
|
|
||
|
plt.tick_params(direction='in')
|
||
|
plt.legend(loc=2,frameon=False)
|
||
|
plt.grid(linestyle=':',linewidth=1)
|
||
|
plt.xlabel('Time [ps]')
|
||
|
plt.ylabel('MSD [$\AA^2$]')
|
||
|
|
||
|
plt.savefig('msd.pdf', dpi=1200, format='pdf')
|
||
|
# plt.show()
|