Advanced Features of gamma_surface.py

Stacking Faults of Specific Dislocations

A feature of dislocations which make them challenging to model is that some dislocation systems can dissociate, creating two partial dislocations connected by a finite-length stacking fault. In some contexts such as in the development of Machine Learning Interatomic Potentials (MLIPs), it may be desirable to model the stacking fault in isolation.

The classes GammaSurface and StackingFault offer parameterisation based on the specific classes of matscipy.dislocation. Instead of passing a miller index to surface_direction, we can instead pass a class or instance of a class that subclasses CubicCrystalDislocation or CubicCrystalDissociatedDislocation (e.g. classes like DiamondGlideScrew, BCCEdge100Dislocation or FCCEdge110Dislocation).

As an example, the DiamondGlideScrew class allows the user to model the Glide Screw dislocation in diamond, which dissociates into two \(30^\circ\) partial dislocations connected by a stacking fault defined by the surface_direction (111) and the glide_direction (11-2).

import numpy as np
from matscipy.dislocation import DiamondGlideScrew, get_elastic_constants
from matscipy.gamma_surface import StackingFault
from matscipy.calculators.manybody.explicit_forms.tersoff_brenner import \
                                   TersoffBrenner, Brenner_PRB_42_9458_C_I
from matscipy.calculators.manybody import Manybody

calc = Manybody(**TersoffBrenner(Brenner_PRB_42_9458_C_I))

# the function accepts any ASE type of calculator
alat, C11, C12, C44 = get_elastic_constants(calculator=calc, symbol="C", verbose=False)
print(f"alat = {alat}")
C_screw = DiamondGlideScrew(alat, C11, C12, C44, symbol="C")

C_screw_bulk, C_screw_dislo = C_screw.build_cylinder(radius=25, partial_distance=20)

view = C_screw.view_cyl(C_screw_dislo, scale=0.6) 

view.control.spin([0, 1, 0], np.math.pi) # flip along y-axis to align with SF visualisation
view.control.zoom(0.7)
view
/usr/lib/python3/dist-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.17.3 and <1.25.0 is required for this version of SciPy (detected version 1.26.4
  warnings.warn(f"A NumPy version >={np_minversion} and <{np_maxversion}"
/usr/local/lib/python3.10/dist-packages/matscipy/dislocation.py:485: FutureWarning: Import StrainFilter from ase.filters
  sf = StrainFilter(unit_cell)
alat = 3.360528114483162
/tmp/ipykernel_8740/605338894.py:19: DeprecationWarning: `np.math` is a deprecated alias for the standard library `math` module (Deprecated Numpy 1.25). Replace usages of `np.math` with `math`
  view.control.spin([0, 1, 0], np.math.pi) # flip along y-axis to align with SF visualisation

We will use the StackingFault class to try and model the stacking fault we see in the above dissociated dislocation plot. The plot made use of Common Neighbour Analysis (CNA) to provide useful colours for the atoms according to the identified crystal structure. This is also available in the .show() methods of the StackingFault and GammaSurface classes, using the CNA_color=True argument.

from visualisation import show_HTML
fault = StackingFault(alat, DiamondGlideScrew, symbol="C")
fault.generate_images(n=9, cell_move=False, z_reps=2, vacuum=True)
anim = fault.show(CNA_color=True)
show_HTML(anim)

We can see that CNA gives the same orange colour we see in the dislocation part way through the stacking fault sweep. With nine total images along the path, the middle image number five corresponds to the perfect stacking fault structure. It can be seen that atomic stacking of image five is exactly the same as the stacking fault region between two partial dislocations. This helps to confirm that we have generated a similar local structure.

Accessing Different Stacking Fault Planes

The Diamond (111) surface is interesting, as it has two distinct planes, called “glide” and “shuffle”, with the same (111) normal direction. Selection of which plane you are modelling depends on which z ordinate in the crystal basis you choose to cut at. Because in the previous example we parameterised the stacking fault with DiamondGlideScrew (which is a dislocation along the glide plane, as the name would suggest), we achieved a stacking fault on the glide plane. To achieve the related stacking fault on the shuffle plane, we can use the argument z_offset to add an offset (in Angstrom) and shift to the different plane. For this carbon crystal, an offset of 0.84 Angstrom gets us to the shuffle plane.

fault = StackingFault(alat, DiamondGlideScrew, symbol="C")
fault.generate_images(n=9, cell_move=False, z_reps=2, z_offset=0.84, vacuum=True)
anim = fault.show(CNA_color=True)
show_HTML(anim)

Stacking Faults in more complex systems

GammaSurface and StackingFault generate a base structure from the input arguments in a very similar manner to the dislocation classes in matscipy.dislocation. This means that instead of supplying a lattice constant + symbol + crystalstructure, we can instead pass an atoms object. As an example, let’s revisit GaAs from the multispecies dislocation docs:

Note

As with the dislocation classes, GammaSurface and StackingFault are only guaranteed to work when passed cubic bulk crystals, and cannot themselves model chemical disorder. Any disorder effects should be applied after generate_images() is called.

from ase.build import bulk

# Data from https://doi.org/10.1080/08927022.2011.602975
alat = 11.2402/2

GaAs = bulk("GaAs", crystalstructure="zincblende", cubic=True, a=alat)

fault = StackingFault(GaAs, DiamondGlideScrew)
fault.generate_images(n=9, cell_move=False, z_reps=2, vacuum=True)
anim = fault.show(CNA_color=False)
show_HTML(anim)