# Authors: Arash Dehghan Banadaki <adehgha@ncsu.edu>, Srikanth Patala <spatala@ncsu.edu>
# Copyright (c) 2015, Arash Dehghan Banadaki and Srikanth Patala.
# License: GNU-GPL Style.
# How to cite GBpy:
# Banadaki, A. D. & Patala, S. "An efficient algorithm for computing the primitive bases of a general lattice plane",
# Journal of Applied Crystallography 48, 585-588 (2015). doi:10.1107/S1600576715004446
import numpy as np
import os
import sys
from tools import vrrotvec2mat
[docs]class Lattice(object):
"""
This class contains all the crystallographic information required for each
atom type. Currently there are only two pre-configured atoms available in
class i.e. 'Al' and 'Mg'. Up on need user can create a new instance of this
class with the same attributes. The attributes of this class are:
...
Attributes
----------
elem_type: string
Element of Interest
pearson: string
Pearson symbol for the lattice
lat_params: dictionary
Lattice parameters ('a', 'b', 'c', 'alpha', 'beta', 'gamma')
l_g_go: numpy array
Primitve basis of the lattice
basis_atoms:
Location of the basis atoms in the primitive lattice
cryst_ptgrp: string
Crystallographic point group of the lattice
burgers_mag: float
The smallest burgers vector in the lattice
eam_file:
eam_file name for atomistic simulations
Methods
-------
str
Method for printing the lattice class
Notes
--------
Examples of elem_type
elem_type = 'Mg'; \v
elem_type = 'Al'; \v
elem_type = 'Cu'; \v
elem_type = 'Ni'; \v
elem_type = 'cF_Id'; \v
elem_type = 'cI_Id'; \v
elem_type = 'cP_Id'; \v
elem_type = 'hP_Id'; \v
"""
def __init__(self, *args):
nargs = len(args)
if nargs == 0:
elem_type = 'cF_Id'
else:
elem_type = args[0]
# Simple cubic lattice
# Ideal
if elem_type == 'cP_Id':
self.elem_type = 'cP_Id'
self.pearson = 'cP'
a = 1.0
self.lat_params = {'a': a, 'b': a, 'c': a, 'alpha': np.pi/2,
'beta': np.pi/2, 'gamma': np.pi/2}
b1x = a*np.array([1.0, 0.0, 0.0])
b1y = a*np.array([0.0, 1.0, 0.0])
b1z = a*np.array([0.0, 0.0, 1.0])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
# Point group symmetry of the lattice
self.cryst_ptgrp = 'Oh'
# ------------------------------------------------------------------------------------------------------
# Polonium
if elem_type.lower() == 'po':
self.elem_type = 'Po'
self.pearson = 'cP'
a = 3.35
self.lat_params = {'a': a, 'b': a, 'c': a, 'alpha': np.pi/2,
'beta': np.pi/2, 'gamma': np.pi/2}
b1x = a*np.array([1.0, 0.0, 0.0])
b1y = a*np.array([0.0, 1.0, 0.0])
b1z = a*np.array([0.0, 0.0, 1.0])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
# Point group symmetry of the lattice
self.cryst_ptgrp = 'Oh'
# ------------------------------------------------------------------------------------------------------
# BCC Lattices
# Ideal
if elem_type == 'cI_Id':
self.elem_type = 'cI_Id'
self.pearson = 'cI'
a = 1.0
self.lat_params = {'a': a, 'b': a, 'c': a, 'alpha': np.pi/2,
'beta': np.pi/2, 'gamma': np.pi/2}
b1x = a*np.array([-0.5, 0.5, 0.5])
b1y = a*np.array([ 0.5, -0.5, 0.5])
b1z = a*np.array([ 0.5, 0.5, -0.5])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
# Point group symmetry of the lattice
self.cryst_ptgrp = 'Oh'
# ------------------------------------------------------------------------------------------------------
# $\alpha$-Fe
if elem_type.lower() == 'fe_alpha':
self.elem_type = 'Fe'
self.pearson = 'cI'
a = 2.870
self.lat_params = {'a': a, 'b': a, 'c': a, 'alpha': np.pi/2,
'beta': np.pi/2, 'gamma': np.pi/2}
b1x = a*np.array([-0.5, 0.5, 0.5])
b1y = a*np.array([ 0.5, -0.5, 0.5])
b1z = a*np.array([ 0.5, 0.5, -0.5])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
# Point group symmetry of the lattice
self.cryst_ptgrp = 'Oh'
# ------------------------------------------------------------------------------------------------------
# FCC Lattices
if elem_type == 'cF_Id':
self.elem_type = 'cF_Id'
self.pearson = 'cF'
a = 1.0
self.lat_params = {'a': a, 'b': a, 'c': a, 'alpha': np.pi/2,
'beta': np.pi/2, 'gamma': np.pi/2}
b1x = a*np.array([0.0, 0.5, 0.5])
b1y = a*np.array([0.5, 0.0, 0.5])
b1z = a*np.array([0.5, 0.5, 0.0])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
# Point group symmetry of the lattice
self.cryst_ptgrp = 'Oh'
# ------------------------------------------------------------------------------------------------------
if elem_type.lower() == 'al':
self.elem_type = 'Al'
self.pearson = 'cF'
a = 4.05
a_ang = np.pi/2
self.lat_params = {'a': a, 'b': a, 'c': a, 'alpha': a_ang, 'beta': a_ang, 'gamma': a_ang}
self.cryst_ptgrp = 'Oh'
self.burgers_mag = a / np.sqrt(2)
self.eam_file = np.array(['alloy', 'Al99.eam.alloy'])
b1x = a*np.array([0.0, 0.5, 0.5])
b1y = a*np.array([0.5, 0.0, 0.5])
b1z = a*np.array([0.5, 0.5, 0.0])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
self.basis_atoms = np.array([0, 0, 0])
# Hexagonal Lattices
# ------------------------------------------------------------------------------------------------------
if elem_type.lower() == 'hp_id':
self.elem_type = 'hP_Id'
self.pearson = 'hP'
a = 1.0
b = a
CAratio = 1.633
c = a*CAratio
a_ang = np.pi/2
b_ang = np.pi/2
g_ang = 2*np.pi/3
self.lat_params = {'a': a, 'b': b, 'c': c, 'alpha': a_ang, 'beta': b_ang, 'gamma': g_ang}
self.cryst_ptgrp = 'D6h'
self.burgers_mag = a
b1x = a*np.array([1., 0., 0.])
b1y = np.dot(vrrotvec2mat(np.array([0., 0., 1., g_ang])), b1x)
b1z = c*np.array([0., 0., 1.])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
self.basis_atoms = np.array([[0., 0., 0.], [1./3, 2./3, 1./2]])
# ------------------------------------------------------------------------------------------------------
if elem_type.lower() == 'hp_ca':
if nargs < 2:
raise Exception('Provide the c/a ratio')
elif nargs == 2:
self.elem_type = 'hP_ca'
ca_ratio = args[1]
self.pearson = 'hP'
a = 1.0
b = a
c = a*ca_ratio
a_ang = np.pi/2
b_ang = np.pi/2
g_ang = 2*np.pi/3
self.lat_params = {'a': a, 'b': b, 'c': c, 'alpha': a_ang, 'beta': b_ang, 'gamma': g_ang}
self.cryst_ptgrp = 'D6h'
b1x = a*np.array([1., 0., 0.])
b1y = np.dot(vrrotvec2mat(np.array([0., 0., 1., g_ang])), b1x)
b1z = c*np.array([0., 0., 1.])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
# ------------------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------------------
if elem_type.lower() == 'mg':
self.elem_type = 'Mg'
self.pearson = 'hP'
a = 3.181269601; b = a; CAratio = 1.632993162; c = a*CAratio
a_ang = np.pi/2; b_ang = np.pi/2; g_ang = 2*np.pi/3;
self.lat_params = {'a': a, 'b': b, 'c': c, 'alpha': a_ang, 'beta': b_ang, 'gamma': g_ang}
self.cryst_ptgrp = 'D6h'
self.burgers_mag = a
self.eam_file = np.array(['fs', 'Mg.eam.fs'])
b1x = a*np.array([1., 0., 0.])
b1y = np.dot(vrrotvec2mat(np.array([0., 0., 1., g_ang])), b1x)
b1z = c*np.array([0., 0., 1.])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
self.basis_atoms = np.array([[0., 0., 0.], [1./3, 2./3, 1./2]])
# ------------------------------------------------------------------------------------------------------
#### Tetragonal Lattices
# ------------------------------------------------------------------------------------------------------
if elem_type.lower() == 'tp_id':
self.elem_type = 'tP_Id'
self.pearson = 'tP'
a = 1.0; b = a; CAratio = 1.2; c = a*CAratio
a_ang = np.pi/2; b_ang = np.pi/2; g_ang = np.pi/2;
self.lat_params = {'a': a, 'b': b, 'c': c, 'alpha': a_ang, 'beta': b_ang, 'gamma': g_ang}
self.cryst_ptgrp = 'D4h'
b1x = a*np.array([1., 0., 0.])
b1y = a*np.array([0., 1., 0.])
b1z = c*np.array([0., 0., 1.])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
# ------------------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------------------
if elem_type.lower() == 'tp_ca':
if nargs < 2:
raise Exception('Provide the c/a ratio')
elif nargs == 2:
self.elem_type = 'tP_ca'
ca_ratio = args[1]
self.pearson = 'tP'
a = 1.0; b = a; c = a*ca_ratio
a_ang = np.pi/2; b_ang = np.pi/2; g_ang = np.pi/2;
self.lat_params = {'a': a, 'b': b, 'c': c, 'alpha': a_ang, 'beta': b_ang, 'gamma': g_ang}
self.cryst_ptgrp = 'D4h'
b1x = a*np.array([1., 0., 0.])
b1y = a*np.array([0., 1., 0.])
b1z = c*np.array([0., 0., 1.])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
# ------------------------------------------------------------------------------------------------------
# Rhombohedral lattices
# ------------------------------------------------------------------------------------------------------
if elem_type.lower() == 'hr_id':
self.elem_type = 'hR_Id'
self.pearson = 'hR'
## Lattice Parameters for Corundum
a = 4.75
c = 12.982
## Using the relation between hexagonal and rhombohedral lattices
tau = 1/3 - (a**2/c**2)/2;
cos_ang = tau/(1 - 2*tau);
a_ang = np.arccos(cos_ang)
self.lat_params = {'a': a, 'b': a, 'c': a, 'alpha': a_ang, 'beta': a_ang, 'gamma': a_ang}
k1 = a*np.sqrt((2 - 2*cos_ang)/3.0)
k2 = a*np.sqrt((1 + 2*cos_ang)/3.0)
b1x = np.array([ np.sqrt(3)*k1/2, k1/2, k2])
b1y = np.array([-np.sqrt(3)*k1/2, k1/2, k2])
b1z = np.array([0, -k1, k2])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
self.cryst_ptgrp = 'D3d'
# ------------------------------------------------------------------------------------------------------
if elem_type.lower() == 'hr_ca':
if nargs < 2:
raise Exception('Provide the c/a ratio')
elif nargs == 2:
self.elem_type = 'hR_ca'
ca_ratio = args[1]
self.pearson = 'hR'
a = 1
c = a*ca_ratio
## Using the relation between hexagonal and rhombohedral lattices
tau = 1./3. - (a**2/c**2)/2;
cos_ang = tau/(1 - 2*tau);
a_ang = np.arccos(cos_ang)
self.lat_params = {'a': a, 'b': a, 'c': a, 'alpha': a_ang, 'beta': a_ang, 'gamma': a_ang}
k1 = a*np.sqrt((2 - 2*cos_ang)/3.0)
k2 = a*np.sqrt((1 + 2*cos_ang)/3.0)
b1x = np.array([ np.sqrt(3)*k1/2, k1/2, k2])
b1y = np.array([-np.sqrt(3)*k1/2, k1/2, k2])
b1z = np.array([0, -k1, k2])
self.l_g_go = np.column_stack((b1x, b1y, b1z))
self.cryst_ptgrp = 'D3d'
# ------------------------------------------------------------------------------------------------------
def __str__(self):
l1 = self
str1 = 'Lattice:'
str1 += 'Pearson Symbol: %s \n' %(l1.pearson)
str1 += 'Lattice Parameters: \n a = %f \t b = %f \t c = %f \t alpha = %f \t beta = %f \t gamma = %f \n' \
%(l1.lat_params['a'], l1.lat_params['b'], l1.lat_params['c'],
l1.lat_params['alpha'], l1.lat_params['beta'], l1.lat_params['gamma'])
str1 += 'Point Group: %s \n' %(l1.cryst_ptgrp)
str1 += 'Primitive lattice (l_g_go): \n'
str1 += str(l1.l_g_go)
str1 += '\n'
str1 += 'Crystal Point group: '
str1 += self.cryst_ptgrp
str1 += '\n'
return str1
# ------------------------------------------------------------------------------------------------------