Structure AnalysisΒΆ
[1]:
%matplotlib inline
# these two lines are only necessary to make the jupyter notebooks run on binder
import sys
sys.path.insert(0, "../..")
# we load all necessary modules
from aimstools.structuretools import Structure
import ase.io
# We load the structure from a file
strc = Structure("MoS2_2H_1L.xyz")
# Reading the structure from a file calls the ase.io.read function, similar to this line:
atoms = ase.io.read("MoS2_2H_1L.xyz")
# Alternatively, the Structure object can also be initialized from an ase.atoms.Atoms object:
strc = Structure(atoms)
# The Structure inherits all properties of the ase.atoms.Atoms object and can also be initialized in the same way:
strc = Structure(positions=atoms.positions, cell=atoms.cell, symbols=atoms.symbols)
# We can check whether this structure is recognized as being two-dimensional:
print("Structure is two-dimensional:", strc.is_2d())
Structure is two-dimensional: True
[2]:
from ase.build import make_supercell
# The Structure object can be treated like any ase.atoms.Atoms object:
supercell = make_supercell(strc, [[2,0,0],[0,2,0],[0,0,2]])
# However, to ensure compatibility, this will actually return an ase.atoms.Atoms object:
print("Type of the supercell:", repr(supercell))
Type of the supercell: Atoms(symbols='MoS2MoS2MoS2MoS2MoS2MoS2MoS2MoS2', pbc=True, cell=[[6.32, 0.0, 0.0], [-3.16, 5.47328056, 0.0], [0.0, 0.0, 200.0]], masses=...)
[3]:
# We can convert the supercell back to a Structure object easily:
strc = Structure(supercell)
# In this supercell, we can look for non-bonded fragments:
fragments = strc.find_fragments()
for i, (indices, part) in enumerate(fragments):
print("Fragment Nr. {:d} consists of the following indices of the original structure:\n {}".format(i, indices))
print("The chemical formula of the fragment is {}".format(part.get_chemical_formula()))
print("---")
Fragment Nr. 0 consists of the following indices of the original structure:
[0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20]
The chemical formula of the fragment is Mo4S8
---
Fragment Nr. 1 consists of the following indices of the original structure:
[3, 4, 5, 9, 10, 11, 15, 16, 17, 21, 22, 23]
The chemical formula of the fragment is Mo4S8
---
[4]:
# To get back to the primitive unit, we can use the standardize function:
old_lengths = strc.cell.lengths()
strc.standardize(symprec=1e-3, to_primitive=True)
new_lengths = strc.cell.lengths()
print("Old lengths: a = {:.4f}, b = {:.4f}, c = {:.4f}".format(*old_lengths))
print("New lengths: a = {:.4f}, b = {:.4f}, c = {:.4f}".format(*new_lengths))
# This method can also be used to symmetrize structures.
# If you set to_primitive=False, you will obtain the conventional cell.
Old lengths: a = 6.3200, b = 6.3200, c = 200.0000
New lengths: a = 3.1600, b = 3.1600, c = 100.0000
[5]:
%matplotlib inline
# In jupyter notebooks, we can get a nice representation with nglview.
# Outside of jupyter, only the matplotlib viewer is available.
# The Structure.view() method is a wrapper for the ase.visualize.view() method.
strc = Structure("Ni2S3_bulk.xyz")
v = strc.view(viewer="ngl")
v.view.add_ball_and_stick()
v.view.add_unitcell()
v.view.camera = "orthographic"
v