def get_local_currents(path,ext,atoms, h, s, ef, G0r, GamL,GamR, bias,\ basis, indices, cutoff = 0.10, direction=2, ignore = [], trans_real=None): """ Calculate and plot local currents. The Green's functions and selfenergies must have been dumped on an energy grid. Parameters: atoms: ase atoms object Atom you wish the local currents calculated for. basis: basis specification GPAW style. String or library. Example: 'dzp', {H:'dzp'} etc. indices: list indices of energies at which to calculate local currents. dump: Boolean if dump=False the local current are not plotted. Instead the tranmission across a surface is calculated. cutoff: float or 1D array if local current between atom is smaller than cutoff no arrow is drawn. If integer, transmission is first calculated. direction: integer transport direction ignore: list: indices for atoms to have have plotted local currents. Useful if atom are e.g. close to leads where current is not conserved. """ dim = len(h) K = np.empty((dim, dim)) arrows = np.zeros((len(atoms), len(atoms))) Tt = GamL.dot(G0r).dot(GamR).dot(G0r.T.conj()) # print Tt.trace(), trans_real # exit() energy = ef # Sigma_el_L= Sigma_el_L_left + Sigma_el_L_right G0L = 1j * G0r.dot(GamL).dot(G0r.T.conj()) # G0L *= bias # print G0L #get lesser Greens function # G0L = dot3( G0r , Sigma_el_L , G0r.T.conj() )#np.dot(G0r[:,:,e],np.dot(Sigma_el_L[:,:,e],dagger(G0r[:,:,e])))# V = h - energy * s #Sigma_el_r[:,:,index] K_mn = np.multiply(V, G0L.T) - np.multiply(V.T, G0L) K_mn[range(dim), range(dim)] = 0 #set diagonal zero K[:, :] = np.real(K_mn) # print K_mn # print np.real(K).max() # exit() # np.set_printoptions(precision=2, suppress=True) #get currents between atoms from gpaw.lcao.tools import get_bfi2 # print "getting arrows..." trans = 0 dic = {} for atom in atoms: dic[atom.index] = get_bfi2(atoms.get_chemical_symbols(), basis, [atom.index]) for n, atom1 in enumerate(atoms): # print n, "of ", len(atoms) bfs1 = dic[atom1.index] for m, atom2 in enumerate(atoms): if m == n: # print m, "m" continue if n in ignore or m in ignore: # print n, "n" continue bfs2 = dic[atom2.index] arrows[n, m] = K[:, :].take(bfs1, axis=0).take(bfs2, axis=1).sum(axis=(0, 1)) # print arrows[n,m,:] if atom1.position[2] < 10.0 and atom2.position[2] > 10.0: # print arrows[n,m] trans += arrows[n, m] np.save('arrows.npy', arrows) # print trans, Tt.trace(), trans_real # exit() f = open(path + ext, 'w') f.write('wireframe off \n background white; \n') f.write('load "file://{0}/central_region.xyz" \n'.format(path)) # text_file.write("set defaultdrawarrowscale 0.1 \n") norm = np.abs(arrows[:, :]).max() # print trans_real # print arrows # exit() arrows2 = arrows / norm for atom1 in atoms: for atom2 in atoms: # print np.real(trans_real) # if atom2.position[direction]-atom1.position[direction]<0.0: # print "hi" # continue # print np.abs(arrows[atom1.index, atom2.index]), cutoff*np.real(trans_real) if np.abs(arrows[atom1.index, atom2.index]) < cutoff * np.real(trans_real): # print "arrow too small, continuing" continue p2 = np.sign( arrows[atom1.index, atom2.index]) #positive or negative contribution p2 = atom1.position[2] - atom2.position[ 2] #positive or negative contribution if p2 > 0.0: c = 'red' o1 = atom1.position o2 = atom2.position else: c = 'red' o1 = atom2.position o2 = atom1.position diam = np.abs(arrows2[atom1.index, atom2.index]) / 2 # print atom1.index, atom2.index, c, diam f.write( 'draw arrow%d_%d arrow {%f %f %f} {%f %f %f} diameter %.6f color %s \n' % (atom2.index, atom1.index, o2[0], o2[1], o2[2], o1[0], o1[1], o1[2], diam, c)) f.write('rotate 90 \n') f.write('background white \n') f.write('write file:/{0}plots/interatomic_current.png'.format(path)) # print "got arrows" # exit() # plot_local_currents(atoms,basis=basis,K=K,energies=[ef],transmission=trans_real) # print trans, "Trans" return trans
def all_this(atoms, calc, path, basis, basis_full, xc, FDwidth, kpts, mode, h, vacuum=4): wfs = calc.wfs from ase.dft.kpoints import monkhorst_pack from ase.io import write as ase kpt = monkhorst_pack((1, 1, 1)) H_kin = wfs.T_qMM[0] np.save(path + "H_kin.npy", H_kin) # exit() # path = "/kemi/aj/local_gpaw/data/H20/" # basename = "basis_{0}__xc_{1}__fdwithd_{3}__kpts_{4}__mode_{5}__vacuum_{6}__".format(basis, xc, FDwidth, kpts, mode, vacuum) basename = "basis_{0}__xc_{1}__h_{2}__fdwithd_{3}__kpts_{4}__mode_{5}__vacuum_{6}__".format( basis, xc, h, FDwidth, kpts, mode, vacuum) # basename = "basis_{0}__xc_{1}__a_{2}__c_{3}__d_{4}__h_{5}__fdwithd_{6}__kpts_{7}__mode_{8}__vacuum_{9}__".format(basis,xc,a,c,d,h,FDwidth,kpts,mode,vacuum) a_list = range(0, len(atoms)) symbols = atoms.get_chemical_symbols() bfs = get_bfi2(symbols, basis_full, range(len(a_list))) rot_mat = np.diag(v=np.ones(len(bfs))) c_fo_xi = asc(rot_mat.real.T) # coefficients phi_xg = calc.wfs.basis_functions.gd.zeros(len(c_fo_xi)) wfs = calc.wfs gd0 = calc.wfs.gd calc.wfs.basis_functions.lcao_to_grid(c_fo_xi, phi_xg, -1) np.save(path + basename + "ao_basis_grid", [phi_xg, gd0]) plot_basis(atoms, phi_xg, ns=len(bfs), folder_name=path + "basis/ao") summ = np.zeros(phi_xg[0, :, :, :].shape) ns = np.arange(len(bfs)) for n, phi in zip(ns, phi_xg.take(ns, axis=0)): summ += abs(phi) * abs(phi) write(path + "basis/ao/sum.cube", atoms, data=summ) """Lowdin""" dump_hamiltonian_parallel(path + 'scat_' + basename, atoms, direction='z') atoms.write(path + basename + ".traj") H_ao, S_ao = pickle.load(open(path + 'scat_' + basename + '0.pckl', 'rb')) H_ao = H_ao[0, 0] S_ao = S_ao[0] n = len(S_ao) eig, rot = np.linalg.eig(S_ao) rot = np.dot(rot / np.sqrt(eig), rot.T.conj()) r_mat = np.identity(n) r_mat[:] = np.dot(r_mat, rot) A = r_mat U = np.linalg.inv(A) rot_mat = A c_fo_xi = asc(rot_mat.real.T) # coefficients lowdin_phi_xg = calc.wfs.basis_functions.gd.zeros(len(c_fo_xi)) wfs = calc.wfs gd0 = calc.wfs.gd calc.wfs.basis_functions.lcao_to_grid(c_fo_xi, lowdin_phi_xg, -1) np.save(path + basename + "lowdin_basis", [lowdin_phi_xg]) np.save(path + basename + "lowdin_U", U) plot_basis(atoms, lowdin_phi_xg, ns=len(bfs), folder_name=path + "basis/lowdin") # MO - basis eig, vec = np.linalg.eig(np.dot(np.linalg.inv(S_ao), H_ao)) order = np.argsort(eig) eig = eig.take(order) vec = vec.take(order, axis=1) S_mo = np.dot(np.dot(vec.T.conj(), S_ao), vec) vec = vec / np.sqrt(np.diag(S_mo)) S_mo = np.dot(np.dot(vec.T.conj(), S_ao), vec) H_mo = np.dot(np.dot(vec.T, H_ao), vec) rot_mat = vec c_fo_xi = asc(rot_mat.real.T) # coefficients mo_phi_xg = calc.wfs.basis_functions.gd.zeros(len(c_fo_xi)) wfs = calc.wfs gd0 = calc.wfs.gd calc.wfs.basis_functions.lcao_to_grid(c_fo_xi, mo_phi_xg, -1) np.save(path + basename + "mo_energies", eig) np.save(path + basename + "mo_basis", mo_phi_xg) plot_basis(atoms, mo_phi_xg, ns=len(bfs), folder_name=path + "basis/mo") # eigenchannels from new2 import ret_gf_ongrid, calc_trans, fermi_ongrid,\ lesser_gf_ongrid, lesser_se_ongrid, ret_gf_ongrid2,\ lesser_gf_ongrid2, retarded_gf2 gamma = 1e0 H_cen = H_ao S_cen = S_ao n = len(H_cen) GamL = np.zeros([n, n]) GamR = np.zeros([n, n]) GamL[0, 0] = gamma GamR[n - 1, n - 1] = gamma # #C8 # bfs = get_bfi2(symbols, basis, [23,24]) # print bfs, "left" # GamL[bfs[0],bfs[0]] = GamL[bfs[1],bfs[1]] = gamma # symbols = atoms.get_chemical_symbols() # bfs = get_bfi2(symbols, basis, [21,22]) # print bfs, "right" # GamR[bfs[0],bfs[0]] = GamR[bfs[1],bfs[1]] = gamma # for ef in [eig[22], 0, eig[27]]: for ef in [0]: """Current approx at low temp""" Sigma_r = -1j / 2 * (GamL + GamR) # Gr_approx = retarded_gf2(H_cen, S_cen, ef, Sigma_r) Gr_approx = retarded_gf2(H_cen, S_cen, ef, Sigma_r) # print Gr_approx, "Gr_approx" # from new import calc_trans, ret_gf_ongrid # e_grid = np.arange(eig[15],eig[30],0.001) # Gamma_L = [GamL for en in range(len(e_grid))] # Gamma_R = [GamR for en in range(len(e_grid))] # Gamma_L = np.swapaxes(Gamma_L, 0, 2) # Gamma_R = np.swapaxes(Gamma_R, 0, 2) # Gr = ret_gf_ongrid(e_grid, H_cen, S_cen, Gamma_L, Gamma_R) # trans = calc_trans(e_grid,Gr,Gamma_L,Gamma_R) # np.save("/Users/andersjensen/Desktop/trans.npy",np.array([e_grid,trans])) # Tt = GamL.dot(Gr_approx).dot(GamR).dot(Gr_approx.T.conj()) # print Tt.trace(), "transmission" def get_left_channels(Gr, S, GamL, GamR, nchan=1): g_s_ii = Gr lambda_l_ii = GamL lambda_r_ii = GamR s_mm = S s_s_i, s_s_ii = np.linalg.eig(s_mm) s_s_i = np.abs(s_s_i) s_s_sqrt_i = np.sqrt(s_s_i) # sqrt of eigenvalues s_s_sqrt_ii = np.dot(s_s_ii * s_s_sqrt_i, s_s_ii.T.conj()) s_s_isqrt_ii = np.dot(s_s_ii / s_s_sqrt_i, s_s_ii.T.conj()) lambdab_r_ii = np.dot(np.dot(s_s_isqrt_ii, lambda_r_ii), s_s_isqrt_ii) a_l_ii = np.dot(np.dot(g_s_ii, lambda_l_ii), g_s_ii.T.conj()) # AL ab_l_ii = np.dot(np.dot(s_s_sqrt_ii, a_l_ii), s_s_sqrt_ii) # AL in lowdin lambda_i, u_ii = np.linalg.eig(ab_l_ii) # lambda and U ut_ii = np.sqrt(lambda_i / (2.0 * np.pi)) * u_ii # rescaled m_ii = 2 * np.pi * np.dot(np.dot(ut_ii.T.conj(), lambdab_r_ii), ut_ii) T_i, c_in = np.linalg.eig(m_ii) T_i = np.abs(T_i) channels = np.argsort(-T_i) c_in = np.take(c_in, channels, axis=1) T_n = np.take(T_i, channels) v_in = np.dot(np.dot(s_s_isqrt_ii, ut_ii), c_in) return T_n, v_in T_n, v_in = get_left_channels(Gr_approx, S_cen, GamL, GamR) def get_eigenchannels(Gr, GamR): """ Calculate the eigenchannels from G Gamma G """ A = Gr.dot(GamL).dot(Gr.T.conj()) Teigs, Veigs = np.linalg.eig(A) order = np.argsort(Teigs) Teigs = Teigs.take(order) Veigs = Veigs.take(order, axis=1) return Teigs, Veigs # T_n, v_in = get_eigenchannels(Gr_approx,GamL) # print T_n # eig, vec = np.linalg.eig(Tt) # order = np.argsort(eig) # eig = eig.take(order) # vec = vec.take(order, axis=1) # print v_in # print np.abs(v_in) # print eig, "eigs" # rot_mat = np.abs(v_in) rot_mat = v_in.real # rot_mat = vec # print rot_mat c_fo_xi = asc(rot_mat.T) # coefficients # print c_fo_xi # print c_fo_xi.max(), c_fo_xi.min() # exit() # c_fo_xi = asc(rot_mat)#coefficients teig_phi_xg = calc.wfs.basis_functions.gd.zeros(len(c_fo_xi)) wfs = calc.wfs gd0 = calc.wfs.gd calc.wfs.basis_functions.lcao_to_grid(c_fo_xi, teig_phi_xg, -1) np.save(path + basename + "eigenchannels__ef_{0}.npy".format(ef), teig_phi_xg) np.save(path + basename + "Teig__ef_{0}.npy".format(ef), eig) plot_eig(atoms, teig_phi_xg, ns=2, folder_name=path + "basis/eigchan", ext="real_ef_{0}".format(ef)) # rot_mat = np.abs(v_in) rot_mat = v_in.imag # rot_mat = vec # print rot_mat c_fo_xi = asc(rot_mat.T) # coefficients # print c_fo_xi # print c_fo_xi.max(), c_fo_xi.min() # exit() # c_fo_xi = asc(rot_mat)#coefficients teig_phi_xg = calc.wfs.basis_functions.gd.zeros(len(c_fo_xi)) wfs = calc.wfs gd0 = calc.wfs.gd calc.wfs.basis_functions.lcao_to_grid(c_fo_xi, teig_phi_xg, -1) np.save(path + basename + "eigenchannels__ef_{0}.npy".format(ef), teig_phi_xg) np.save(path + basename + "Teig__ef_{0}.npy".format(ef), eig) plot_eig(atoms, teig_phi_xg, ns=2, folder_name=path + "basis/eigchan", ext="imag_ef_{0}".format(ef))
def plot_local_currents(atoms, basis, K, energies, transmission, cutoff=0.1, ignore=[], direction=2): from ase.io import write from gpaw.lcao.tools import get_bfi2 dic = {} for atom in atoms: dic[atom.index] = get_bfi2(atoms.get_chemical_symbols(), basis, [atom.index]) mask = np.ones((len(atoms), len(atoms))) for bf1 in ignore: for bf2 in ignore: mask[bf1, bf2] = 0.0 arrows = np.zeros(len(atoms), len(atoms)) f = open('flux_e%.2f.dat' % energies[0], 'w') f.write('wireframe off \n background white; \n') #get arrows for n, atom1 in enumerate(atoms): bfs1 = dic[atom1.index] for m, atom2 in enumerate(atoms): if m == n: arrows[n, m] = 0.0 continue if n in ignore or m in ignore: arrows[n, m] = 0.0 continue bfs2 = dic[atom2.index] arrows[n, m] = K[:, :].take(bfs1, axis=0).take(bfs2, axis=1).sum(axis=(0, 1)) norm = np.abs(np.multiply(mask, arrows[:, :])).max() arrows2 = arrows[:, :] / norm for atom1 in atoms: for atom2 in atoms: # print direction, "direction" exit() if atom2.position[direction] - atom1.position[direction] < 0.0: continue if np.abs(arrows[e, atom1.index, atom2.index]) < cutoff * transmission[e]: # print "arrow too small, continuing" continue p2 = np.sign( arrows[e, atom1.index, atom2.index]) #positive or negative contribution if p2 > 0.0: c = 'red' o1 = atom1.position o2 = atom2.position else: c = 'blue' o1 = atom2.position o2 = atom1.position diam = np.abs(arrows2[atom1.index, atom2.index]) # print atom1.index, atom2.index, c, diam # print "hi" f.write( 'draw arrow%d_%d arrow {%f %f %f} {%f %f %f} diameter %.6f color %s \n' % (atom1.index, atom2.index, o1[0], o1[1], o1[2], o2[0], o2[1], o2[2], diam, c)) np.save('arrows.npy', arrows) return
from gpaw.lcao.tools import get_bfi2 # Import Hamiltonian and overlap matrix. This example is calculated using GPAW. h = np.loadtxt('files_benzene/h.txt') s = np.loadtxt('files_benzene/s.txt') # Import Atoms object mol = read('files_benzene/benzene.txt') # Specify number of electron pairs. ne = 15 # Generate library which links atoms to basis functions basis_dic = {} for atom in mol: basis_dic[atom.index]=get_bfi2(mol.get_chemical_symbols(), 'dzp', [atom.index]) # Initialize benz = NO(h=h, s=s, ne=ne, mol=mol, basis_dic = basis_dic) # Get Natural Atomic Orbitals (NAOs) NAO = benz.get_NAO() # Get indices of NAOs with occupancy of 1. For benzene, these correspond to the pz-orbitals. pzs = benz.get_single_occupancy_NAO_indices(threshold=0.01) # plot pz orbitals to make sure you are happy with the basis plot_basis(benz.NAOs, mol, pzs, basis = 'dzp', folder_name='./files_benzene/pzs') ##### transport ####### # Specify energy grid.
def __init__( self, gpwfilename, fixedenergy=0.0, spin=0, ibl=True, basis="sz", zero_fermi=False, pwfbasis=None, lcaoatoms=None, projection_data=None, ): calc = GPAW(gpwfilename, txt=None, basis=basis) assert calc.wfs.gd.comm.size == 1 assert calc.wfs.kpt_comm.size == 1 assert calc.wfs.band_comm.size == 1 if zero_fermi: try: Ef = calc.get_fermi_level() except NotImplementedError: Ef = calc.get_homo_lumo().mean() else: Ef = 0.0 self.ibzk_kc = calc.get_ibz_k_points() self.nk = len(self.ibzk_kc) self.eps_kn = [calc.get_eigenvalues(kpt=q, spin=spin) - Ef for q in range(self.nk)] self.M_k = [sum(eps_n <= fixedenergy) for eps_n in self.eps_kn] print "Fixed states:", self.M_k self.calc = calc self.dtype = self.calc.wfs.dtype self.spin = spin self.ibl = ibl self.pwf_q = [] self.norms_qn = [] self.S_qww = [] self.H_qww = [] if ibl: if pwfbasis is not None: pwfmask = basis_subset2(calc.atoms.get_chemical_symbols(), basis, pwfbasis) if lcaoatoms is not None: lcaoindices = get_bfi2(calc.atoms.get_chemical_symbols(), basis, lcaoatoms) else: lcaoindices = None self.bfs = get_bfs(calc) if projection_data is None: V_qnM, H_qMM, S_qMM, self.P_aqMi = get_lcao_projections_HSP( calc, bfs=self.bfs, spin=spin, projectionsonly=False ) else: V_qnM, H_qMM, S_qMM, self.P_aqMi = projection_data H_qMM -= Ef * S_qMM for q, M in enumerate(self.M_k): if pwfbasis is None: pwf = ProjectedWannierFunctionsIBL(V_qnM[q], S_qMM[q], M, lcaoindices) else: pwf = PWFplusLCAO(V_qnM[q], S_qMM[q], M, pwfmask, lcaoindices) self.pwf_q.append(pwf) self.norms_qn.append(pwf.norms_n) self.S_qww.append(pwf.S_ww) self.H_qww.append(pwf.rotate_matrix(self.eps_kn[q][:M], H_qMM[q])) else: if projection_data is None: V_qnM = get_lcao_projections_HSP(calc, spin=spin) else: V_qnM = projection_data for q, M in enumerate(self.M_k): pwf = ProjectedWannierFunctionsFBL(V_qnM[q], M, ortho=False) self.pwf_q.append(pwf) self.norms_qn.append(pwf.norms_n) self.S_qww.append(pwf.S_ww) self.H_qww.append(pwf.rotate_matrix(self.eps_kn[q])) for S in self.S_qww: print "Condition number: %0.1e" % condition_number(S)
def __init__(self, gpwfilename, fixedenergy=0., spin=0, ibl=True, basis='sz', zero_fermi=False, pwfbasis=None, lcaoatoms=None, projection_data=None): calc = GPAW(gpwfilename, txt=None, basis=basis) assert calc.wfs.gd.comm.size == 1 assert calc.wfs.kd.comm.size == 1 assert calc.wfs.bd.comm.size == 1 if zero_fermi: try: Ef = calc.get_fermi_level() except NotImplementedError: Ef = calc.get_homo_lumo().mean() else: Ef = 0.0 self.ibzk_kc = calc.get_ibz_k_points() self.nk = len(self.ibzk_kc) self.eps_kn = [ calc.get_eigenvalues(kpt=q, spin=spin) - Ef for q in range(self.nk) ] self.M_k = [sum(eps_n <= fixedenergy) for eps_n in self.eps_kn] print('Fixed states:', self.M_k) self.calc = calc self.dtype = self.calc.wfs.dtype self.spin = spin self.ibl = ibl self.pwf_q = [] self.norms_qn = [] self.S_qww = [] self.H_qww = [] if ibl: if pwfbasis is not None: pwfmask = basis_subset2(calc.atoms.get_chemical_symbols(), basis, pwfbasis) if lcaoatoms is not None: lcaoindices = get_bfi2(calc.atoms.get_chemical_symbols(), basis, lcaoatoms) else: lcaoindices = None self.bfs = get_bfs(calc) if projection_data is None: V_qnM, H_qMM, S_qMM, self.P_aqMi = get_lcao_projections_HSP( calc, bfs=self.bfs, spin=spin, projectionsonly=False) else: V_qnM, H_qMM, S_qMM, self.P_aqMi = projection_data H_qMM -= Ef * S_qMM for q, M in enumerate(self.M_k): if pwfbasis is None: pwf = ProjectedWannierFunctionsIBL(V_qnM[q], S_qMM[q], M, lcaoindices) else: pwf = PWFplusLCAO(V_qnM[q], S_qMM[q], M, pwfmask, lcaoindices) self.pwf_q.append(pwf) self.norms_qn.append(pwf.norms_n) self.S_qww.append(pwf.S_ww) self.H_qww.append( pwf.rotate_matrix(self.eps_kn[q][:M], H_qMM[q])) else: if projection_data is None: V_qnM = get_lcao_projections_HSP(calc, spin=spin) else: V_qnM = projection_data for q, M in enumerate(self.M_k): pwf = ProjectedWannierFunctionsFBL(V_qnM[q], M, ortho=False) self.pwf_q.append(pwf) self.norms_qn.append(pwf.norms_n) self.S_qww.append(pwf.S_ww) self.H_qww.append(pwf.rotate_matrix(self.eps_kn[q])) for S in self.S_qww: print('Condition number: %0.1e' % condition_number(S))
}) atoms.set_calculator(calc) atoms.get_potential_energy() # Converge everything! Ef = atoms.calc.get_fermi_level() wfs = calc.wfs kpt = monkhorst_pack((1, 1, 1)) basename = "basis_{0}__xc_{1}__h_{2}__fdwithd_{3}__kpts_{4}__mode_{5}__vacuum_{6}__".format( basis, xc, h, FDwidth, kpts, mode, vacuum) dump_hamiltonian_parallel(path + 'scat_' + basename, atoms, direction='z') a_list = range(0, len(atoms)) symbols = atoms.get_chemical_symbols() bfs = get_bfi2(symbols, basis_full, range(len(a_list))) rot_mat = np.diag(v=np.ones(len(bfs))) c_fo_xi = asc(rot_mat.real.T) # coefficients phi_xg = calc.wfs.basis_functions.gd.zeros(len(c_fo_xi)) wfs = calc.wfs gd0 = calc.wfs.gd calc.wfs.basis_functions.lcao_to_grid(c_fo_xi, phi_xg, -1) np.save(path + basename + "ao_basis_grid", [phi_xg, gd0]) plot_basis(atoms, phi_xg, ns=len(bfs), folder_name=path + "basis/ao") print('fermi is', Ef) # MO - basis H_ao, S_ao = pickle.load(open(path + 'scat_' + basename + '0.pckl', 'rb')) H_ao = H_ao[0, 0] S_ao = S_ao[0]