Skip to content

Commit

Permalink
Merge pull request #1044 from hillarypan/master
Browse files Browse the repository at this point in the history
added BrunnerNN class that uses Brunner's method to calculate near neighbors
  • Loading branch information
shyuep committed Feb 20, 2018
2 parents eb0c361 + 89e6ff8 commit 37f0325
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
54 changes: 54 additions & 0 deletions pymatgen/analysis/local_env.py
Expand Up @@ -2008,3 +2008,57 @@ def get_order_parameters(self, structure, n, indices_neighs=None, \
0]) ** 2)

return ops


class BrunnerNN(NearNeighbors):
"""
Determine coordination number using Brunner's algorithm which counts the
atoms that are within the largest gap in differences in real space
interatomic distances.
Note: Might be highly inaccurate in certain cases.
Args:
mode (str): type of neighbor-finding approach, where "reciprocal"
will use Brunner's method of largest reciprocal gap in
interatomic distances, "relative" will use Brunner's method of largest
relative gap in interatomic distances, and "real" will use Brunner's
method of largest gap in interatomic distances.
Defaults to "reciprocal" method.
tol (float): tolerance parameter for bond determination
(default: 1E-4).
cutoff (float): cutoff radius in Angstrom to look for near-neighbor
atoms. Defaults to 8.0.
"""

def __init__(self, mode="reciprocal", tol=1.0e-4, cutoff=8.0):
self.mode = mode
self.tol = tol
self.cutoff = cutoff

def get_nn_info(self, structure, n):

site = structure[n]
neighs_dists = structure.get_neighbors(site, self.cutoff)
ds = [i[-1] for i in neighs_dists]
ds.sort()

if self.mode == "reciprocal":
ns = [1.0 / ds[i] - 1.0 / ds[i + 1] for i in range(len(ds) - 1)]
elif self.mode == "relative":
ns = [ds[i] / ds[i + 1] for i in range(len(ds) - 1)]
elif self.mode == "real":
ns = [ds[i] - ds[i + 1] for i in range(len(ds) - 1)]
else:
raise ValueError("Unknown Brunner CN mode.")

d_max = ds[ns.index(max(ns))]
siw = []
for s, dist in neighs_dists:
if dist < d_max + self.tol:
w = ds[0] / dist
siw.append({'site': s,
'image': self._get_image(s.frac_coords),
'weight': w,
'site_index': self._get_original_site(structure, s)})
return siw
23 changes: 22 additions & 1 deletion pymatgen/analysis/tests/test_local_env.py
Expand Up @@ -12,7 +12,7 @@
VoronoiNN, JMolNN, \
MinimumDistanceNN, MinimumOKeeffeNN, MinimumVIRENN, \
get_neighbors_of_site_with_index, site_is_of_motif_type, \
NearNeighbors, LocalStructOrderParas
NearNeighbors, LocalStructOrderParas, BrunnerNN
from pymatgen import Element, Structure, Lattice
from pymatgen.util.testing import PymatgenTest
from pymatgen.io.cif import CifParser
Expand Down Expand Up @@ -157,6 +157,27 @@ def test_all_nn_classes(self):
self.assertAlmostEqual(MinimumVIRENN(tol=0.01).get_cn(
self.cscl, 0), 8)

self.assertAlmostEqual(BrunnerNN(tol=0.01).get_cn(
self.diamond, 0), 4)
self.assertAlmostEqual(BrunnerNN(tol=0.01).get_cn(
self.nacl, 0), 6)
self.assertAlmostEqual(BrunnerNN(tol=0.01).get_cn(
self.cscl, 0), 14)

self.assertAlmostEqual(BrunnerNN(mode="real", tol=0.01).get_cn(
self.diamond, 0), 16)
self.assertAlmostEqual(BrunnerNN(mode="real", tol=0.01).get_cn(
self.nacl, 0), 18)
self.assertAlmostEqual(BrunnerNN(mode="real", tol=0.01).get_cn(
self.cscl, 0), 8)

self.assertAlmostEqual(BrunnerNN(mode="relative", tol=0.01).get_cn(
self.diamond, 0), 16)
self.assertAlmostEqual(BrunnerNN(mode="relative", tol=0.01).get_cn(
self.nacl, 0), 18)
self.assertAlmostEqual(BrunnerNN(mode="relative", tol=0.01).get_cn(
self.cscl, 0), 8)

def tearDown(self):
del self.diamond
del self.nacl
Expand Down

0 comments on commit 37f0325

Please sign in to comment.