Skip to content

Commit

Permalink
Added atomic distances
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurentRDC committed Nov 12, 2018
1 parent c0f370d commit a42771d
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 3 deletions.
40 changes: 40 additions & 0 deletions crystals/atom.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,46 @@ def coords_cartesian(self):
return real_coords(self.coords_fractional, np.eye(3))
return real_coords(self.coords_fractional, self.lattice.lattice_vectors)

def distance_fractional(self, atm):
"""
Calculate the distance between atoms in fractional coordinates.
Parameters
----------
atm : ``crystals.Atom`` instance
Returns
-------
dist : float
Distance in fractional coordinates
"""
return np.linalg.norm(self.coords_fractional - atm.coords_fractional)

def distance_cartesian(self, atm):
"""
Calculate the distance between atoms in cartesian coordinates.
If the parent lattices are different, an error is raised.
Parameters
----------
atm : ``crystals.Atom`` instance
Returns
-------
dist : float
Distance in Angstroms.
Raises
------
RuntimeError : if atoms are not defined on the same lattice.
"""
if self.lattice != atm.lattice:
raise RuntimeError(
"Cartesian distance is undefined if atoms are sitting on different lattices."
)

return np.linalg.norm(self.coords_cartesian - atm.coords_cartesian)

def transform(self, *matrices):
"""
Transforms the real space coordinates according to a matrix.
Expand Down
35 changes: 33 additions & 2 deletions docs/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,43 @@ or :class:`Lattice) can be accessed using the :meth:`Atom.coords_cartesian` meth
>>> fractional = carbon.coords_fractional
>>> real = carbon.coords_cartesian

Atomic distances
----------------

The distance between two atoms can be calculated by taking their difference::

>>> copper = Atom('Cu', coords = [0,0,0])
>>> silver = Atom('Ag', coords = [1,0,0])
>>> dist = silver - copper # distance in fractional coordinates
>>> dist
>>> silver.distance_fractional(copper) # distance in fractional coordinates
1.0

The cartesian distance between two atoms sitting *on the same lattice* is also possible:

>>> from crystals import Crystal
>>> graphite = Crystal.from_database('C')
>>>
>>> carbon1, carbon2, *_ = tuple(graphite)
>>> carbon1.coords_cartesian
array([0.000, 0.000, 5.033])
>>> carbon2.coords_cartesian
array([1.232, 0.711, 5.033])
>>> carbon1.distance_cartesian(carbon2)
1.4225981762919013

If atoms are not sitting on the same lattice, calculating the distance should not be defined. In this case, an exception is raised:

>>> from crystals import Crystal
>>> gold = Crystal.from_database('Au')
>>> silver = Crystal.from_database('Ag')
>>>
>>> gold1, *_ = tuple(gold)
>>> silver1, *_ = tuple(silver)
>>>
>>> gold1.distance_cartesian(silver1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "(...omitted...)\crystals\atom.py", line 181, in distance_cartesian
"Cartesian distance is undefined if atoms are sitting on different lattices."
RuntimeError: Cartesian distance is undefined if atoms are sitting on different lattices.

:ref:`Return to Top <user_guide>`
3 changes: 2 additions & 1 deletion tests/test_atom.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def test_distance(self):
""" Test the distance between atoms """
atm1 = Atom("He", [0, 0, 0])
atm2 = Atom("He", [1, 0, 0])
self.assertEqual(atm1 - atm2, 1)
self.assertEqual(atm1.distance_fractional(atm2), 1)
self.assertEqual(atm1.distance_fractional(atm2), atm2.distance_fractional(atm1))


if __name__ == "__main__":
Expand Down

0 comments on commit a42771d

Please sign in to comment.