Source code for bp_basis

import numpy as np
from fractions import gcd
import integer_manipulations as int_man
import find_csl_dsc as fcd
import sys
import os
file_dir = os.path.dirname(os.path.realpath(__file__))
# Load the following modules from tools directory
path_dir1 = file_dir + '/tools/'
sys.path.append(path_dir1)
import Col
import lll_reduction as lll_red
import smith_nf as snf
# -----------------------------------------------------------------------------------------------------------


[docs]def check_int_mats(l1, l2): """ The function checks whether or not the elements of $A_{left}^{-1}$*B are integers Parameters ---------- l1, l2 : numpy arrays of same dimensions Returns ------- cond: numpy boolean array """ l1_linv = np.dot(np.linalg.inv(np.dot(l1.T, l1)), l1.T) cond = int_man.int_check(np.dot(l1_linv, l2), 10) return cond # -----------------------------------------------------------------------------------------------------------
[docs]def check_2d_csl(l_pl1_g1, l_pl2_g1, l_csl_g1): """ The function checks whether or not the CSL basis may be expressed as a linear integer combination of the plane bases of planes 1 and 2 Parameters ---------------- l_pl1_g1, l_pl2_g1: numpy arrays of basis vectors for plane 1 and 2 in the g1 reference frame """ ct = 1 str1 = 'Check ' + str(ct) + ' : --> ' if check_int_mats(l_pl1_g1, l_csl_g1).all(): str2 = 'YES\n' color = 'yel' else: raise Exception('The 2D CSL does not contain base1.') print str1, txt = Col() txt.c_prnt(str2, color) # -------------------------- ct += 1 str1 = 'Check ' + str(ct) + ' : --> ' if check_int_mats(l_pl2_g1, l_csl_g1).all(): str2 = 'YES\n' color = 'yel' else: raise Exception('The 2D CSL does not contain base2.') print str1, txt = Col() txt.c_prnt(str2, color) # -----------------------------------------------------------------------------------------------------------
[docs]def lbi_dioph_soln(a, b, c): """ Computes the diophantaine solution for the equation ax + by = c """ k = abs(gcd(a, b)) if np.fmod(c, k) != 0.0: raise Exception('No Solutions Exist') mult = c / k # b1 = extended_euclid(a, b) ####<----------------- must be verified b1 = np.zeros(2) b1[0], b1[1], _ = snf.extgcd(a, b) x1 = mult * b1[0] x2 = mult * b1[1] if a*x1 + b*x2 - c != 0: raise Exception('Something wrong with the Algorithm') tk = -(b-a)/(a**2 + b**2) tk_mat = np.array([[np.ceil(tk)], [np.floor(tk)]]) x_sol = np.array([[x1], [x1]]) + tk_mat * b y_sol = np.array([[x2], [x2]]) - tk_mat * a sol_mag = np.power(x_sol, 2) + np.power(y_sol, 2) ind = np.where(sol_mag == min(sol_mag))[0] int_soln = [x_sol[ind[0]], y_sol[ind[0]]] return int_soln # -----------------------------------------------------------------------------------------------------------
[docs]def compute_basis_vec(d_eq): """ The function computes y1, y2, y3 such that h\*y1 + k\*y2 + l\*y3 = 0 and modulus of y1 is a minimum Parameters ----------------- d_eq: numpy array or list of size 3 and dimension 1 h = d_eq[0], k = d_eq[1], l = d_eq[2] Returns ------------ np.array([y1, y2, y3]) """ hp = d_eq[0] kp = d_eq[1] lp = d_eq[2] # Find the minimum y1 such that y2 and y3 are solutions of the equation. # kp*y2 + lp*y3 = -hp*y1 (Diaphontane Equation). # Solutions exist if gcd(kp,lp) is a multiple of hp*y1 cond = 0 y1 = 1 while cond == 0: if np.fmod(hp * y1, gcd(kp, lp)) == 0: cond = 1 else: y1 += 1 # Diophantine Equation: ax + by = c # To solve: f = kp*x + lp*y + hp*m = 0; avar = kp bvar = lp cvar = -hp * y1 int_soln = lbi_dioph_soln(avar, bvar, cvar) y2 = int_soln[0] y3 = int_soln[1] if (kp*y2 + lp*y3 + hp*y1) != 0: raise Exception('Error with Diophantine solution') return np.array([y1, y2, y3]) # -----------------------------------------------------------------------------------------------------------
[docs]def bp_basis(bp_g1, lattice): """ The function computes the primitve basis of the plane if the boundary plane normal and the underlying lattice are specified Parameters --------------- bp_g1: numpy array Boundary plane normal in 'g1' reference frame lattice: Lattice class Attributes of the under lattice Returns ----------- l_pl_g1: numpy array The primitive basis of the plane with boundary plane normal bp_g1 """ l_g1_go1 = lattice.l_g_go # Metric Tensor $G = S^T S$ g_g1 = np.dot(l_g1_go1.T, l_g1_go1) rat_tols = np.array([1e-05, 1e-06, 1e-07, 1e-08, 1e-09, 1e-10]) d_eq = np.zeros((len(rat_tols), 3)) d_eq_norms = np.zeros((len(rat_tols), 1)) for i in range(len(rat_tols)): d_eq[i, :] = int_man.int_finder(np.dot(bp_g1.T, g_g1), rat_tols[i]) d_eq_norms[i] = np.sqrt(np.dot(d_eq[i, :], d_eq[i, :].T)) # Add repeatablity of the numerator t_ind = np.where(d_eq_norms == min(d_eq_norms)) hp = d_eq[t_ind[0][0], 0] kp = d_eq[t_ind[0][0], 1] lp = d_eq[t_ind[0][0], 2] if hp == 0 and kp == 0 and lp == 0: raise Exception('hkl indices cannot all be zero') else: if hp != 0 and kp != 0 and lp != 0: gc_f1_p = gcd(kp, lp) bv1_g1 = np.array([[0], [-lp / gc_f1_p], [kp / gc_f1_p]]) bv2_g1 = compute_basis_vec([hp, kp, lp]) else: if hp == 0: if kp == 0: bv1_g1 = np.array([[1], [1], [0]]) bv2_g1 = np.array([[1], [-1], [0]]) elif lp == 0: bv1_g1 = np.array([[1], [0], [1]]) bv2_g1 = np.array([[1], [0], [-1]]) else: gc_f1_p = gcd(kp, lp) bv1_g1 = np.array([[0], [-lp / gc_f1_p], [kp / gc_f1_p]]) bv2_g1 = compute_basis_vec([hp, kp, lp]) else: if kp == 0: if lp == 0: bv1_g1 = np.array([[0], [1], [1]]) bv2_g1 = np.array([[0], [1], [-1]]) else: gc_f1_p = gcd(hp, lp) bv1_g1 = np.array([[-lp / gc_f1_p], [0], [hp / gc_f1_p]]) bv2_g1 = np.array([[-lp / gc_f1_p], [1], [hp / gc_f1_p]]) else: if lp == 0: gc_f1_p = gcd(hp, kp) bv1_g1 = np.array([[-kp / gc_f1_p], [hp / gc_f1_p], [0]]) bv2_g1 = np.array([[-kp / gc_f1_p], [hp / gc_f1_p], [1]]) # The reduced basis vectors for the plane l_pl_g1 = lll_red.lll_reduction(np.column_stack([bv1_g1, bv2_g1])) return l_pl_g1 # -----------------------------------------------------------------------------------------------------------
[docs]def pl_density(l_pl_g1, l_g1_go1): """ For a given two-dimensional plane basis, the planar density is computed Parameters --------------- l_pl_g1: numpy array l_g1_go1: numpy array Basis vectors of the underlying lattice with respect to the orthogonal reference frame 'go1' Returns ---------- pd: float Planar density = (1/area covered by plane basis) """ l_pl_go1 = np.dot(l_g1_go1, l_pl_g1) planar_basis_area = np.linalg.norm(np.cross(l_pl_go1[:, 0], l_pl_go1[:, 1])) pd = 1.0/planar_basis_area return pd # -----------------------------------------------------------------------------------------------------------
[docs]def csl_finder_2d(l_pl1_g1, l_pl2_g1): """ Given two plane bases, the 2D CSL bases are obtined by utilizing the smith normal form of the transformation between the two bases Parameters --------------- l_pl1_g1, l_pl2_g1: numpy array Basis vectors of planes 1 and 2 expressed in g1 reference frame Returns --------------- l_2d_csl_g1: numpy array The basis vectors of the 2D CSL expressed in g1 reference frame """ l1 = np.array(l_pl1_g1) l2 = np.array(l_pl2_g1) # L2 = L1*T (T := T_Pl1ToPl2_Pl1) l1_linv = np.dot(np.linalg.inv(np.dot(l1.T, l1)), l1.T) t = np.dot(l1_linv, l2) # # Obtain N1 and N2 n1, a = int_man.int_mult(t) if int_man.int_check(a, 12).all: a = np.around(a) # A = U*E*V'; E is a diagonal matrix u, e, v = snf.smith_nf(a) l2_n = np.dot(l2, np.linalg.inv(v.T)) l_2d_csl_g1 = fcd.cls_elem_div_thm_l2(e/n1, l2_n) if int_man.int_check(l_2d_csl_g1, 10).all(): l_2d_csl_g1 = np.around(l_2d_csl_g1) else: raise Exception('Wrong CSL computation') l_2d_csl_g1 = lll_red.lll_reduction(l_2d_csl_g1[:, 0:2]) return l_2d_csl_g1 # -----------------------------------------------------------------------------------------------------------
[docs]def gb_2d_csl(bp1_g1, t_g1tog2_g1, lattice): """ For a given boundary plane normal 'bp1_g1' and the misorientation matrix 't_g1tog2_g1', the two-dimensional CSL lattice is computed Parameters --------------- bp1_g1: numpy array t_g1tog2_g1: numpy array lattice: Lattice class Returns ----------- l_2d_csl_g1: numpy array The basis vectors of the 2D CSL expressed in g1 reference frame l_pl1_g1, l_pl2_g1: numpy arrays Basis vectors of planes 1 and 2 expressed in g1 reference frame """ l_g1_go1 = lattice.l_g_go bp1_go1 = np.dot(l_g1_go1, bp1_g1) l_g2_g1 = t_g1tog2_g1 l_g2_go1 = np.dot(l_g1_go1, l_g2_g1) l_go1_g2 = np.linalg.inv(l_g2_go1) bp2_g2 = int_man.int_finder(np.dot(-l_go1_g2, bp1_go1)) l_pl1_g1 = bp_basis(bp1_g1, lattice) l_pl2_g2 = bp_basis(bp2_g2, lattice) l_pl2_g1 = np.dot(l_g2_g1, l_pl2_g2) l_2d_csl_g1 = csl_finder_2d(l_pl1_g1, l_pl2_g1) return l_2d_csl_g1, l_pl1_g1, l_pl2_g1 # -----------------------------------------------------------------------------------------------------------
[docs]def bicryst_planar_den(bp1_go1, t_g1tog2_go1, lattice): """ The function computes the planar densities of the planes 1 and 2 and the two-dimensional CSL Parameters --------------- bp1_go1: numpy array The boundary plane normal components in go1 reference frame t_g1tog2_go1: numpy array Transformation matrix from g1 to g2 in go1 reference frame lattice: Lattice class Attributes of the underlying lattice Returns ----------- pl_den_pl1, pl_den_pl2: numpy array The planar density of planes 1 and 2 pl_den_csl: numpy array The planare density of the two-dimensional CSL """ l_g1_go1 = lattice.l_g_go l_go1_g1 = np.linalg.inv(l_g1_go1) bp1_g1 = np.dot(l_go1_g1, bp1_go1) t_g1tog2_g1 = np.dot(l_go1_g1, np.dot(t_g1tog2_go1, l_g1_go1)) l_2d_csl_g1, l_pl1_g1, l_pl2_g1 = gb_2d_csl(bp1_g1, t_g1tog2_g1, lattice) check_2d_csl(l_pl1_g1, l_pl2_g1, l_2d_csl_g1) pl_den_pl1 = pl_density(l_pl1_g1, l_g1_go1) pl_den_pl2 = pl_density(l_pl2_g1, l_g1_go1) pl_den_csl = pl_density(l_2d_csl_g1, l_g1_go1) return pl_den_pl1, pl_den_pl2, pl_den_csl # -----------------------------------------------------------------------------------------------------------