Skip to content

Commit 6b6a44d

Browse files
authored
Merge pull request #88 from amcadmus/devel
support rdf
2 parents 1e0908b + 167832f commit 6b6a44d

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

dpdata/md/rdf.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import numpy as np
2+
3+
def rdf(sys,
4+
sel_type = [None, None],
5+
max_r = 5,
6+
nbins = 100) :
7+
"""
8+
compute the rdf of a system
9+
10+
Parameters
11+
----------
12+
sys : System or LabeledSystem
13+
The dpdata system
14+
sel_type: list
15+
List of size 2. The first element specifies the type of the first atom,
16+
while the second element specifies the type of the second atom.
17+
Both elements can be ints or list of ints.
18+
If the element is None, all types are specified.
19+
Examples are sel_type = [0, 0], sel_type = [0, [0, 1]] or sel_type = [0, None]
20+
max_r: float
21+
Maximal range of rdf calculation
22+
nbins: int
23+
Number of bins for rdf calculation
24+
"""
25+
return compute_rdf(sys['cells'], sys['coords'], sys['atom_types'],
26+
sel_type = sel_type,
27+
max_r = max_r,
28+
nbins = nbins)
29+
30+
def compute_rdf(box,
31+
posis,
32+
atype,
33+
sel_type = [None, None],
34+
max_r = 5,
35+
nbins = 100) :
36+
nframes = box.shape[0]
37+
xx = None
38+
all_rdf = []
39+
for ii in range(nframes):
40+
xx, rdf = _compute_rdf_1frame(box[ii], posis[ii], atype, sel_type, max_r, nbins)
41+
all_rdf.append(rdf)
42+
all_rdf = np.array(all_rdf).reshape([nframes, -1])
43+
all_rdf = np.average(all_rdf, axis = 0)
44+
return xx, all_rdf
45+
46+
def _compute_rdf_1frame(box,
47+
posis,
48+
atype,
49+
sel_type = [None, None],
50+
max_r = 5,
51+
nbins = 100) :
52+
all_types = list(set(list(np.sort(atype))))
53+
if sel_type[0] is None:
54+
sel_type[0] = all_types
55+
if sel_type[1] is None:
56+
sel_type[1] = all_types
57+
if type(sel_type[0]) is not list:
58+
sel_type[0] = [sel_type[0]]
59+
if type(sel_type[1]) is not list:
60+
sel_type[1] = [sel_type[1]]
61+
natoms = len(posis)
62+
from ase import Atoms
63+
import ase.neighborlist
64+
atoms = Atoms(positions=posis, cell=box, pbc=[1,1,1])
65+
nlist = ase.neighborlist.NeighborList(max_r, self_interaction=False, bothways=True, primitive=ase.neighborlist.NewPrimitiveNeighborList)
66+
nlist.update(atoms)
67+
stat = np.zeros(nbins)
68+
hh = max_r / float(nbins)
69+
for ii in range(natoms) :
70+
# atom "0"
71+
if atype[ii] in sel_type[0]:
72+
indices, offsets = nlist.get_neighbors(ii)
73+
for jj, os in zip(indices, offsets):
74+
# atom "1"
75+
if atype[jj] in sel_type[1]:
76+
posi_jj = atoms.positions[jj] + np.dot(os, atoms.get_cell())
77+
diff = posi_jj - atoms.positions[ii]
78+
dr = np.linalg.norm(diff)
79+
# if (np.linalg.norm(diff- diff_1)) > 1e-12 :
80+
# raise RuntimeError
81+
si = int(dr / hh)
82+
if si < nbins:
83+
stat[si] += 1
84+
# count the number of atom1
85+
c0 = 0
86+
for ii in sel_type[0]:
87+
c0 += np.sum(atype == ii)
88+
# count the number of atom1
89+
c1 = 0
90+
for ii in sel_type[1]:
91+
c1 += np.sum(atype == ii)
92+
rho1 = c1 / np.linalg.det(box)
93+
# compute rdf
94+
for ii in range(nbins):
95+
vol = 4./3. * np.pi * ( ((ii+1)*hh) ** 3 - ((ii)*hh) ** 3 )
96+
rho = stat[ii] / vol
97+
stat[ii] = rho / rho1 / c0
98+
xx = np.arange(0, max_r-1e-12, hh)
99+
return xx, stat
100+
101+
if __name__ == '__main__':
102+
import dpdata
103+
sys = dpdata.System('out.lmp')
104+
xx, stat = rdf(sys, sel_type = [[0], None], max_r = 8, nbins = 100)
105+
res = np.concatenate([xx, stat]).reshape([2, -1])
106+
np.savetxt('rdf.out', res.T)

0 commit comments

Comments
 (0)