2. How to find a reduced planar basis for a Grain Boundary 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
import os
import inspect
import pickle

2.1. Miller Indices:

Please refer to sections 1.1-1.3 of the tutorial for a comprehensive discussion about Miller Indices and common conventions. 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

Other conventions in defining the Miller Indices are ultimately converted to the above definition in GBpy.

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.


2.2. Problem Definition:

In this tutorial we would like to find a reduced planar basis for a $\Sigma3$ Grain Boundary(GB) plane with the normal vector [2 3 1]. Note that the normal is defined in the orthogonal reference frame (supercell f.c.c) of the lower crystal (Crystal 1).

Note that whenever we are working with a plane in GBpy we need to be careful with the reference in which the planes are defined and what the Miller Indices of that plane are. For GBs however there is a rich set of functions that perform all the conversions. The user only needs to be consistent with the GBpy's conventions.

In the following tutorial we demonstrate the features of the gb_2d_csl function.


2.3. Extracting the Misorientation Operator:

In Tutorial 3 we have extensively discussed the structure of the database of misorientations that ships with GBpy. In this tutorial we first extract the transformation matrix associated with $\Sigma3$ misorientation that can be found in "cF_Id_csl_common_rotations.pkl".

In [2]:
gbpy_dir = os.path.dirname((inspect.getfile(GBpy)))
pkl_dir = gbpy_dir + '/pkl_files'
pkl_file = pkl_dir + '/cF_Id_csl_common_rotations.pkl'
pkl_content = pickle.load(open(pkl_file))
N3 = pkl_content['3']['N'][0]
D3 = pkl_content['3']['D'][0]
Sigma3 = N3/D3
print Sigma3
[[ 0.66666667 -0.33333333  0.66666667]
 [ 0.66666667  0.66666667 -0.33333333]
 [-0.33333333  0.66666667  0.66666667]]

Also, from Tutorial 1 we know the components of a primitive f.c.c in supercell reference frame, i.e. $\Lambda_{p}^{po}$, is defined as:

In [3]:
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[3]:
array([[ 0. ,  0.5,  0.5],
       [ 0.5,  0. ,  0.5],
       [ 0.5,  0.5,  0. ]])

At this point we have all we need to find a reduced basis for the GB plane.


3.3. Finding the GB Planar Basis (2D CSL Basis):

The function specifically developed for this task is named gb_2d_csl() that can be accessed from GBpy.bp_basis.gb_2d_csl().

Let's go over all the inputs, outputs and the options that are available for gb_2d_csl.

$\Lambda_{2D~CSL}^{p1}, \Lambda_{Crystal 1}^{p1}, \Lambda_{Crystal 2}^{p1} $ = gb_2d_csl (indices, $T^{ref}$, $\Lambda_{p}^{po}$, index_type, T_reference)

Inputs:

The function accepts 5 inputs.

  1. indices: plane indices.
  2. $T^{ref}$: 3x3 Misorientation Matrix defined in T_reference.
  3. $\Lambda_{p}^{po}$: 3x3 components of a primitive f.c.c in supercell reference frame.
  4. index_type: is a string that defines the type of indices that has been passed for the plane normal. There are 3 options. 'miller_index', 'normal_go', 'normal_g'. The default value is 'miller_index' meaning that if you don't specify any value for this field, GBpy assumes that your indices are defined as Miller Indices. If you choose the 'normal_go' option, it means that your indices are defined in the orthogonal basis, and finally 'normal_g' means that the indicies are defined in primitive basis of the underlying lattice.
  5. T_reference: is a string that specifies the reference frame in which the misorientation matrix, i.e. $T^{ref}$ is expressed. There are 2 options. 'g1', 'go1'. The default value is 'g1' meaning that if you don't specify any value for this field, GBpy assumes that your transormation matrix is defined with respect to the primitive basis vectors of the crystal 1(lower crystal). If you use the supplied pickle files, this is always the case and default value is correct. In case your misorientation matrix is defined in orthogonal reference frame then you should choose the string 'go1'.

* Note that for the input types that are supposed to be strings you need to provide the exact same words.

Outputs:

The function generates 3 outputs:

  1. $\Lambda_{2D~CSL}^{p1}$: 3x2 matrix; A reduced 2D basis for the GB plane (2D CSL) expressed in the primitive basis of the crystal 1(lower crystal). Each column contains one of the basis vectors.
  2. $\Lambda_{Crystal 1}^{p1}$: 3x2 matrix; A reduced 2D basis for the specified plane in crystal 1 (lower crystal) expressed in the primitive basis of the crystal 1(lower crystal). Each column contains one of the basis vectors.
  3. $\Lambda_{Crystal 2}^{p1}$: 3x2 matrix; A reduced 2D basis for the specified plane in crystal 2 (upper crystal) expressed in the primitive basis of the crystal 1(lower crystal). Each column contains one of the basis vectors.

* Note the reference frame for all the bases are expressed with respect to the primitive basis of the crystal 1(lower crystal).


In this example our indices are provided in the orthogonal basis therefore we have to overwrite the default value of the index_type and change it to normal_go. The default value of the T_reference, i.e. 'g1' is a correct choice as we are using the supplied misorintation data from the database. Let's import the appropriate package and abbreviate it for the sake of simplicity.

In [4]:
import GBpy.bp_basis as plb
inds = np.array([2, 3, 1])
t_mat = Sigma3
index_type  = 'normal_go'
T_reference = 'g1'

L_2d_csl_p1, L_pl1_p1, L_pl2_p1 = plb.gb_2d_csl(inds, t_mat, L_p_po, index_type, T_reference)

print 'L_2d_csl_p1:\n', L_2d_csl_p1, '\n-------'
print 'L_pl1_p1:\n', L_pl1_p1, '\n-------'
print 'L_pl2_p1:\n', L_pl2_p1, '\n-------'
L_2d_csl_p1:
[[-2.  1.]
 [ 1.  7.]
 [ 1. -5.]] 
-------
L_pl1_p1:
[[ 2.  1.]
 [-1.  2.]
 [-1. -2.]] 
-------
L_pl2_p1:
[[ 2.          0.33333333]
 [-1.         -2.66666667]
 [-1.          1.33333333]] 
-------

Note in the above naming of variables L_2d_csl_p1, L_pl1_p1 and L_pl2_p1 are respectively $\Lambda_{2D~CSL}^{p1}, \Lambda_{Crystal 1}^{p1}$ and $\Lambda_{Crystal 2}^{p1} $.

From the Tutorial 1 we found out that the Miller Indices associated with the normal vector [2 3 1] (defined in orthogonal reference frame) is going to be (4 3 5). So Let's experiment with the input type and pass the Miller Indices as the index. Accordingly we need to change the index_type varibale to the 'miller_index' which is the default value. In other words both index_type and T_reference will have the default variables and no overwriting is necessary.

In [5]:
inds = np.array([4, 3, 5])
t_mat = Sigma3
index_type  = 'miller_index'
T_reference = 'g1'

L_2d_csl_p1, L_pl1_p1, L_pl2_p1 = plb.gb_2d_csl(inds, t_mat, L_p_po, index_type, T_reference)

print 'L_2d_csl_p1:\n', L_2d_csl_p1, '\n-------'
print 'L_pl1_p1:\n', L_pl1_p1, '\n-------'
print 'L_pl2_p1:\n', L_pl2_p1, '\n------'
L_2d_csl_p1:
[[-2.  1.]
 [ 1.  7.]
 [ 1. -5.]] 
-------
L_pl1_p1:
[[ 2.  1.]
 [-1.  2.]
 [-1. -2.]] 
-------
L_pl2_p1:
[[ 2.          0.33333333]
 [-1.         -2.66666667]
 [-1.          1.33333333]] 
------

Evidently the results are the same; indicating that as long as user is consistent with the definitions GBpy can successfully process all the conventions and produce the correct result. In the end and as mentioned since the index_type and T_reference will have the default variables specifying them is not necessary and the results will be the same.

In [6]:
inds = np.array([4, 3, 5])
t_mat = Sigma3
index_type  = 'miller_index'
T_reference = 'g1'

L_2d_csl_p1, L_pl1_p1, L_pl2_p1 = plb.gb_2d_csl(inds, t_mat, L_p_po)

print 'L_2d_csl_p1:\n', L_2d_csl_p1, '\n-------'
print 'L_pl1_p1:\n', L_pl1_p1, '\n-------'
print 'L_pl2_p1:\n', L_pl2_p1, '\n------'
L_2d_csl_p1:
[[-2.  1.]
 [ 1.  7.]
 [ 1. -5.]] 
-------
L_pl1_p1:
[[ 2.  1.]
 [-1.  2.]
 [-1. -2.]] 
-------
L_pl2_p1:
[[ 2.          0.33333333]
 [-1.         -2.66666667]
 [-1.          1.33333333]] 
------

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