1. How to find the 2D Basis of a Plane using GBpy:

Follow the installation manual to receive the GBpy package and import all the required packages that we need for completing this tutorial.

In [1]:
import GBpy
import numpy as np

1.1. Miller Indices and Common Conventions:

Miller Indices are often used to refer to a given crystallograohic plane in crystals. However various conventions are commonly used in determining the Miller Indices that can completely change the plane of reference. For this reason we would like to declare our conventions in defining the Miller Indices to avoid any confusions. By definition Miller Indices are defined as the reciprocal of intercepts of a crystallographic plane with the Unit Cell Basis Vectors. The confusion is often caused by the definition of the Unit Cell. In f.c.c and b.c.c lattices primitive basis vectors are non-orthogonal while the supercell basis vectors are orthogonal. Most importantly since the reciprocal and direct lattices are the identical in f.c.c and b.c.c, the Miller Indices (defined in supercell unit cell) are the same as the plane normal indices. This unique property and convenience of using an orthogonal set of basis vectors is the root cause of the bipartisan approach to defining the Miller Indices. The downfall of such an approach is the fact that it does not have much utility in other types of lattices e.g. hcp. Therefore in GBpy whenever we use the term Miller Indices, we are referring to the reciprocals of intercepts of a crystallographic plane with the primitive Basis Vectors.

Miller Indices: reciprocal of intercepts of a crystallographic plane with the primitive Basis Vectors

or alternatively:

Miller Indices: normal vector indices of the plane defined in primitive reciprocal lattice

The above interchangeable definitions are consistently used in GBpy for referring to Miller Indices. Other conventions in defining the Miller Indices are ultimately converted to the above definition.

In the present tutorial we manually extract various Indices and demonstrate how they can be fed to the GBpy. In practice such conversions are not necessary as long as the user is consistent with the definitions of GBpy, and can be used for verifying the answer.


1.2. Problem Definition:

In this tutorial we would like to find the planar basis of a plane with [2 3 1] normal vector defined in supercell f.c.c basis .

Since the normal vector to the plane is provided in the orthogonal f.c.c basis (supercell basis), first we need to obtain the Miller Indices of the plane to be able to use the GBpy package.


1.3. Finding the Miller Indices:

A vector in the space can be expressed in any basis, of course with varying components. Vector $\vec{v}$ in basis A can be expressed as:

$\vec{v} = \mathcal{B}_{A}~ v_{A}~~(1)$

where $\mathcal{B}_{A}$ is the basis A and $v_{A}$ are the components of $\vec{v}$ in basis A.

Similarly we can define the plane normal $\vec{n}$ in any basis. For instance we can define $\vec{n}$ in supercell f.c.c basis ($\mathcal{B}_{po}$) or in primitive f.c.c basis ($\mathcal{B}_{p}$); we can write:

$\vec{n} = \mathcal{B}_{po}~ n_{po} = \mathcal{B}_{p}~ n_{p} ~~(2)$

We can express the right hand side of the $(2)$ as:

$\mathcal{B}_{po}~ n_{po} = \mathcal{B}_{po} \Lambda_{p}^{po}~ n_{p} \Rightarrow n_{p} = (\Lambda_{p}^{po})^{-1} ~n_{po} \Rightarrow$ $\boxed{n_{p} = \Lambda_{po}^{p}~n_{po}} ~~(3)$

where:

$\Lambda_{po}^{p}$ is a 3x3 matrix with its columns being the components of basis vectors of $po$ in $p$ basis.

Using the highlighted equation we can convert the components of a vector from one basis to the other.

By definition Miller Indices are the components of the plane normal in the primitive reciprocal lattice. Therefore we need to express $\vec{n}$ in the primitive reciprocal lattice basis.

$\vec{n} = \mathcal{B}_{po}~ n_{po} = \mathcal{B}_{p}^{*}~ n_{p}^{*} ~~(4)$

where * is indicative of the reciprocal space. Hence we can write:

$n_{p}^{*} = \Lambda_{po}^{p^{*}}~n_{po} ~~(5)$

Therefore by finding the $\Lambda_{po}^{p^{*}}$ we can find the components of $\vec{n}$ in reciprocal space which will be the Miller Indices of the plane (2 3 1).

The following relationship holds between reciprocal and direct lattice spaces:

$\Lambda_{po}^{p^{*}} = (\Lambda^{po}_{p^{*}})^{-1} = ((\Lambda^{po}_{p})^{*})^{-1}~~(6)$

where $\Lambda^{po}_{p}$ is a known matrix for a given lattice. For a f.c.c lattice with the lattice parameter of $a = 1.0 \unicode{x212B}$, $\Lambda^{po}_{p}$ is the following matrix. This matrix can also be obtained from the lattice class in GBpy for a number of elements. Refer to the GBpy documentation for further details. If we name the $\Lambda^{po}_{p}$ as L_p_po:

In [2]:
L_p_po = 1.0 * np.array([[0.,0.5,0.5],[0.5,0.,0.5],[0.5,0.5,0.]])
L_p_po
Out[2]:
array([[ 0. ,  0.5,  0.5],
       [ 0.5,  0. ,  0.5],
       [ 0.5,  0.5,  0. ]])

From $(6)$ we need to find the reciprocal of the $\Lambda^{po}_{p}$. To do so use the GBpy.find_csl_dsc.reciprocal_mat(). For the sake of convenience we abbreviate the imported function GBpy.find_csl_dsc as fcd:

In [3]:
import GBpy.find_csl_dsc as fcd
L_rp_po = fcd.reciprocal_mat(L_p_po)
L_rp_po
Out[3]:
array([[-1.,  1.,  1.],
       [ 1., -1.,  1.],
       [ 1.,  1., -1.]])

where L_rp_po is:

$(\Lambda_{po}^{p})^{*} = \Lambda_{po}^{p^{*}}$.

All that needs to be done is to invert the $\Lambda^{po}_{p^{*}}$ to find the $\Lambda_{po}^{p^{*}}$

In [4]:
L_po_rp = np.linalg.inv(L_rp_po)
L_po_rp
Out[4]:
array([[ 0. ,  0.5,  0.5],
       [ 0.5,  0. ,  0.5],
       [ 0.5,  0.5,  0. ]])

Notice that for f.c.c lattices conveniently $\Lambda_{po}^{p^{*}} = \Lambda_{po}^{p}$. Finally from $(5)$ we can find the $n_{p}^{*}$ as:

In [5]:
n_po = np.array([2, 3, 1])
n_rp = np.dot(L_po_rp, n_po)
n_rp
Out[5]:
array([ 2. ,  1.5,  2.5])

However since the Miller Indices are ought to be integral we have to find a common scaling factor for all the components such that the result is going to be scalar. We have implemented a function named int_finder that performs this task for a variety of input types and on rows and columns of matrices. For irrational numbers int_finder accepts a tolerance and performs the same operation on the closest rational number within the specified tolerance. You can find this function in the package as: GBpy.integer_manipulations.int_finder(). Therefore we repeat the previous steps and pass the results to the int_finder to obtain an integral answer.

In [6]:
import GBpy.integer_manipulations as int_man
n_rp_integral = int_man.int_finder(n_rp)
n_rp_integral
Out[6]:
array([4, 3, 5])

1.4. Finding the Planar Basis:

From the previous section we found the Miller Indices of an f.c.c plane with the normal of [2 3 1] to be (4 3 5). Now all we have to do is to pass the obtained indices to the appropriate function in GBpy. bp_basis is a function that gets the Miller Indices as the input and returns a 3X2 matrix, where each column is one of the two planar basis vectors. Note that the output of the bp_basis() is always expressed in the primitive lattice basis. Also the obtained vectors are always in the reduced form, meaning that the length of the obtained basis vectors are as close as possible. You can find the bp_basis function in the following path: GBpy.bp_basis.bp_basis()

To find the basis vector of a plane with the Miller Indices of (4 3 5) use the following syntax:

In [7]:
import GBpy.bp_basis as plb
L_planar_p = plb.bp_basis(n_rp_integral)
print L_planar_p
[[ 2.  1.]
 [-1.  2.]
 [-1. -2.]]

To express the obtained basis in the orthogonal basis (i.e. supercell f.c.c) one needs to perform the following conversion of bases:

$\Lambda^{po}_{2D} = \Lambda_{p}^{po} \times \Lambda^{p}_{2D}$

In [8]:
L_planar_po = np.dot(L_p_po, L_planar_p)
L_planar_po
Out[8]:
array([[-1. ,  0. ],
       [ 0.5, -0.5],
       [ 0.5,  1.5]])

At the interface of a bicrystal, the $\Lambda_{2D}^{po}$ provides a basis for the interface. If the two crystals are related to each other by a $\Sigma$-rotation, the obtained $\Lambda_{2D}^{po}$ is a basis for the coincidence site lattice at the interface. Therefore the bicrystal conserves its periodicity in the obtained 2D-basis. In other words the obtained basis is in fact the basis for the unit cell of the bicrystal and since it is in the reduced form, it is going to have the smallest skewness, hence ideal for constructing a periodic simulation box.

The above process is frquently repeated for simulation of grain boundaries. Therefore we have developed a set of functions that make the conversion of indices more convenient and will accept various conventions for the Miller Indices. Please refer to the grain boundary 2D-CSL tutorial for how to use these functions.


Copyright (c) 2015, Arash D. Banadaki, Srikanth Patala