mirror of
https://github.com/triqs/dft_tools
synced 2024-12-22 12:23:41 +01:00
Current version of transport code (to be deleted later)
This commit is contained in:
parent
8251d76553
commit
23096e0e76
942
python/SumK_LDA_Transport.py
Normal file
942
python/SumK_LDA_Transport.py
Normal file
@ -0,0 +1,942 @@
|
|||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
#
|
||||||
|
# Copyright (C) 2011 by M. Aichhorn, L. Pourovskii, V. Vildosola
|
||||||
|
#
|
||||||
|
# TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
# terms of the GNU General Public License as published by the Free Software
|
||||||
|
# Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
# version.
|
||||||
|
#
|
||||||
|
# TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
#=======================================================================================================================
|
||||||
|
# #################################################################
|
||||||
|
# Code for Transport/Optic calculations based on SumK_LDA... class
|
||||||
|
# by Xiaoyu Deng <xiaoyu.deng@gmail.com>
|
||||||
|
# #################################################################
|
||||||
|
#=======================================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
from types import *
|
||||||
|
import numpy
|
||||||
|
|
||||||
|
|
||||||
|
# NEW
|
||||||
|
import pytriqs.utility.dichotomy as Dichotomy
|
||||||
|
# OLD
|
||||||
|
#import pytriqs.Base.Utility.Dichotomy as Dichotomy
|
||||||
|
|
||||||
|
# NEW
|
||||||
|
#from pytriqs.gf.local.descriptors import A_Omega_Plus_B
|
||||||
|
from pytriqs.gf.local import *
|
||||||
|
# OLD
|
||||||
|
#from pytrigs.Base.GF_Local.GF import GF
|
||||||
|
#from pytriqs.Base.GF_local.GFBloc_ImFreq import GFBloc_ImFreq
|
||||||
|
#from pytriqs.Base.GF_Local.GFBloc_ReFreq import GFBloc_ReFreq
|
||||||
|
#from pytriqs.Base.GF_Local.GFBloc_ImTime import GFBloc_ImTime
|
||||||
|
#from pytriqs.Base.GF_Local import GF_Initializers
|
||||||
|
|
||||||
|
# NEW
|
||||||
|
#from pytriqs.operators.operators2 import *
|
||||||
|
# OLD
|
||||||
|
#from pytriqs.Solvers.Operators import *
|
||||||
|
|
||||||
|
# NEW
|
||||||
|
# NOT FOUND
|
||||||
|
# OLD
|
||||||
|
#from pytriqs.Base.Utility.myUtils import Sum
|
||||||
|
|
||||||
|
# NEW
|
||||||
|
import pytriqs.utility.mpi as myMPI
|
||||||
|
# OLD
|
||||||
|
#import pytriqs.Base.Utility.MPI as myMPI
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
#from pytriqs.Wien2k.Symmetry import *
|
||||||
|
|
||||||
|
# NEW
|
||||||
|
from pytriqs.applications.dft.sumk_lda import *
|
||||||
|
from pytriqs.applications.dft.sumk_lda_tools import *
|
||||||
|
#k in xrange(self OLD
|
||||||
|
#from pytriqs.Wien2k.SumK_LDA import SumK_LDA
|
||||||
|
#from pytriqs.Wien2k.SumK_LDA_tools import SumK_LDA_tools
|
||||||
|
|
||||||
|
import string
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import SumK_LDA_Transport_Wien2k_input as Wien
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def Read_Fortran_File (filename):
|
||||||
|
""" Returns a generator that yields all numbers in the Fortran file as float, one by one"""
|
||||||
|
import os.path
|
||||||
|
if not(os.path.exists(filename)) : raise IOError, "File %s does not exists" % filename
|
||||||
|
for line in open(filename, 'r') :
|
||||||
|
for x in line.replace('D', 'E').split() :
|
||||||
|
yield string.atof(x)
|
||||||
|
|
||||||
|
def Read_Fortran_File2(filename):
|
||||||
|
""" Returns a generator that yields all numbers in the Fortran file as float, one by one"""
|
||||||
|
import os.path
|
||||||
|
if not(os.path.exists(filename)) : raise IOError, "File %s does not exists" % filename
|
||||||
|
for line in open(filename, 'r') :
|
||||||
|
for x in line.replace('D', 'E').split() :
|
||||||
|
try:
|
||||||
|
yield string.atof(x)
|
||||||
|
except GeneratorExit:
|
||||||
|
raise
|
||||||
|
except:
|
||||||
|
yield x.replace('E', 'D')
|
||||||
|
|
||||||
|
|
||||||
|
def fermidis(x):
|
||||||
|
return 1.0/(numpy.exp(x)+1)
|
||||||
|
|
||||||
|
# OLD
|
||||||
|
#class TransportEtOptic(SumK_LDA_tools):
|
||||||
|
# NEW
|
||||||
|
class TransportEtOptic(SumkLDATools):
|
||||||
|
"""transport and optic related functions
|
||||||
|
calculates distributions: Tr A(k,w) v(k) A(k, w) v(k) or Tr A(k,w) v(k) A(k, w+Omega) v(k)
|
||||||
|
.based on thi for ik in xrange(selfs distribution other properties could be obtained.
|
||||||
|
!!! worked for cases with spin orbital interaction.
|
||||||
|
!!! for non-SOI, need check! Be careful!.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def initbyWien(self, wiencase):
|
||||||
|
""" read in necessary parameters from wien file.
|
||||||
|
symmetries:
|
||||||
|
volume:
|
||||||
|
velocities:
|
||||||
|
"""
|
||||||
|
|
||||||
|
# k_dep_projection is the general case!.
|
||||||
|
assert self.k_dep_projection == 1, "Not implemented!"
|
||||||
|
|
||||||
|
self.Nspinblocs = self.SP + 1 - self.SO
|
||||||
|
# suffix of wien2k output file
|
||||||
|
self.blocksuffix=[[""],["up","dn"]]
|
||||||
|
|
||||||
|
self.velocities=None
|
||||||
|
self.bandwin=None
|
||||||
|
self.Vol = None
|
||||||
|
self.symm = None
|
||||||
|
self.nsymm = None
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
CASE = Wien.WienStruct(wiencase)
|
||||||
|
CASE.readSGsymm(wiencase)
|
||||||
|
if(self.Nspinblocs == 1): # paramagnetic , without SOI; or spin polarized with SOI
|
||||||
|
self.velocities = [Wien.Velocities(wiencase,bln) for bln in self.blocksuffix[0]]
|
||||||
|
else:
|
||||||
|
self.velocities = [Wien.Velocities(wiencase, bln) for bln in self.blocksuffix[1] ]
|
||||||
|
# read in band window for each k points. "CASE.oubwin".
|
||||||
|
bandwin=self.bandwinfromwiencase(wiencase=wiencase)
|
||||||
|
|
||||||
|
self.bandwin=bandwin
|
||||||
|
self.Vol = CASE.VolumePC
|
||||||
|
self.symm = CASE.symmcartesian
|
||||||
|
self.nsymm = CASE.nsymm
|
||||||
|
myMPI.barrier()
|
||||||
|
self.velocities=myMPI.bcast(self.velocities)
|
||||||
|
self.bandwin=myMPI.bcast(self.bandwin)
|
||||||
|
self.Vol=myMPI.bcast(self.Vol)
|
||||||
|
self.symm=myMPI.bcast(self.symm)
|
||||||
|
self.nsymm=myMPI.bcast(self.nsymm)
|
||||||
|
|
||||||
|
|
||||||
|
def Transportdistribution_Boltz(self, wiencase, mshape=None, broadening=0.01, energywindow=None, Nomega=1000, loadpw=False):
|
||||||
|
"""This is for transport calculation of Boltzmann theory
|
||||||
|
calculate \sum_k Tr vv delta(\omega-enk) which is transportdistribution in Boltzmann theory
|
||||||
|
Just use the LDA hamiltonian and velocity, DMFT self energy is not needed.
|
||||||
|
|
||||||
|
mshape defines the indices of directions. xx,yy,zz,xy,yz,zx.
|
||||||
|
mshape is 3x3 matrix, mshape[0,0]=1 --> calculate xx, mshape[1,1]=1 --> calculate yy, mshape[1,2]=1 --> calculate xy,
|
||||||
|
by default, xx is calculated.
|
||||||
|
"""
|
||||||
|
if mshape==None:
|
||||||
|
mshape=numpy.zeros(9).reshape(3,3)
|
||||||
|
mshape[0,0]=1
|
||||||
|
assert mshape.shape == (3, 3), "mshape should be 3x3"
|
||||||
|
velocities = self.velocities
|
||||||
|
mu = 0
|
||||||
|
assert self.k_dep_projection == 1, "k_dep_projection = 0 is NOT implemented!"
|
||||||
|
|
||||||
|
if energywindow is None:
|
||||||
|
omminplot = -1.0
|
||||||
|
ommaxplot = 1.0
|
||||||
|
else:
|
||||||
|
omminplot = energywindow[0]
|
||||||
|
ommaxplot = energywindow[1]
|
||||||
|
deltaomega = (ommaxplot - omminplot) / Nomega
|
||||||
|
|
||||||
|
# transport distribution :output P(\omega)_xy should has the same dimension as defined in mshape.
|
||||||
|
self.Pw = numpy.zeros((mshape.sum(), Nomega), dtype=numpy.float_)
|
||||||
|
|
||||||
|
mlist = []
|
||||||
|
for ir in xrange(3):
|
||||||
|
for ic in xrange(3):
|
||||||
|
if(mshape[ir][ic] == 1):
|
||||||
|
mlist.append((ir, ic))
|
||||||
|
if loadpw:
|
||||||
|
with open("TD_Boltz_mp.dat", "r") as pwin:
|
||||||
|
for iw in xrange(Nomega):
|
||||||
|
fstr = pwin.readline().split()
|
||||||
|
aomega = iw * deltaomega + omminplot
|
||||||
|
assert abs(float(fstr[0]) - aomega) <= 1e-8, "mesh not match when load transportdistribution"
|
||||||
|
for ipw in range(mshape.sum()): self.Pw[ipw, iw] = float(fstr[ipw + 1])
|
||||||
|
print "Blotz Pw loaded"
|
||||||
|
return
|
||||||
|
|
||||||
|
# for ik=0
|
||||||
|
ik = 0
|
||||||
|
# block_names for green function and self energy
|
||||||
|
bln = self.block_names[self.SO]
|
||||||
|
ntoi = self.names_to_ind[self.SO]
|
||||||
|
|
||||||
|
ikarray = numpy.array(range(self.n_k))
|
||||||
|
for isp in range(self.Nspinblocs):
|
||||||
|
for ik in myMPI.slice_array(ikarray):
|
||||||
|
n_orb = self.n_orbitals[ik][isp]
|
||||||
|
mupat = numpy.ones(n_orb, numpy.float_) * mu
|
||||||
|
Ms = copy.deepcopy(mupat)
|
||||||
|
ind = ntoi[bln[isp]]
|
||||||
|
Ms = numpy.diag(self.hopping[ik,ind,0:n_orb,0:n_orb].real) - mupat
|
||||||
|
if(ik%100==0):
|
||||||
|
print "ik,isp", ik, isp
|
||||||
|
kvel = velocities[isp].vks[ik]
|
||||||
|
|
||||||
|
# in general, bandwindows for Annkw and for velocities are not the same.
|
||||||
|
# one should make sure the same window are using before go further. otherwise the matrix size are not match.
|
||||||
|
Pwtem = numpy.zeros((mshape.sum(), Nomega), dtype=numpy.float_)
|
||||||
|
#symmetry loop
|
||||||
|
# this symmetrization could be done first to speed up... To be done.
|
||||||
|
for Rmat in self.symm:
|
||||||
|
# get new velocity.
|
||||||
|
Rkvel = copy.deepcopy(kvel.vel)
|
||||||
|
for vnb1 in xrange(kvel.bandwin[1] - kvel.bandwin[0] + 1):
|
||||||
|
Rkvel[vnb1][vnb1][:] = numpy.dot(Rmat, Rkvel[vnb1][vnb1][:])
|
||||||
|
|
||||||
|
ipw = 0
|
||||||
|
for (ir, ic) in mlist:
|
||||||
|
for iw in xrange(Nomega):
|
||||||
|
omega = deltaomega * iw + omminplot
|
||||||
|
bmin = max(self.bandwin[isp][ik, 0], kvel.bandwin[0])
|
||||||
|
bmax = min(self.bandwin[isp][ik, 1], kvel.bandwin[1])
|
||||||
|
for ib in xrange(bmax - bmin + 1):
|
||||||
|
ibb = ib + bmin - self.bandwin[isp][ik, 0]
|
||||||
|
ibv = ib + bmin - kvel.bandwin[0]
|
||||||
|
enk = Ms[ibb] - omega
|
||||||
|
Ag = 1.0 / numpy.sqrt(2 * numpy.pi) / broadening * numpy.exp(-enk ** 2 / 2.0 / broadening ** 2)
|
||||||
|
vkr = Rkvel[ibv][ibv][ir]
|
||||||
|
vkc = Rkvel[ibv][ibv][ic]
|
||||||
|
|
||||||
|
#Pwtem[ipw,iw]+=(vkr*vkc*Ag).real
|
||||||
|
Pwtem[ipw, iw] += vkr * vkc * Ag
|
||||||
|
ipw += 1
|
||||||
|
|
||||||
|
self.Pw += Pwtem * self.bz_weights[ik] / self.nsymm
|
||||||
|
myMPI.barrier()
|
||||||
|
self.Pw = myMPI.all_reduce(myMPI.world, self.Pw, lambda x, y : x + y)
|
||||||
|
# for non-magnetic case, the total weight is doubled because of spin degeneracy.
|
||||||
|
self.Pw *= (2 - self.SP)
|
||||||
|
|
||||||
|
# scattering is needed here.
|
||||||
|
self.Pw *= 1.0/numpy.pi/2.0/broadening
|
||||||
|
|
||||||
|
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
with open("TD_Boltz.dat", "w") as pwout:
|
||||||
|
for iw in xrange(Nomega):
|
||||||
|
omega = deltaomega * iw + omminplot
|
||||||
|
pwout.write(str(omega) + " ")
|
||||||
|
for i in range(self.Pw.shape[0]):
|
||||||
|
pwout.write(str(self.Pw[i, iw]) + " ")
|
||||||
|
pwout.write("\n")
|
||||||
|
|
||||||
|
def Transportdistribution(self, wiencase, mshape=None, broadening=0.00, energywindow=None, loadpw=False):
|
||||||
|
"""calculate Tr A(k,w) v(k) A(k, w) v(k).
|
||||||
|
mshape defines the indices of directions. xx,yy,zz,xy,yz,zx.
|
||||||
|
mshape is 3x3 matrix, mshape[0,0]=1 --> calculate xx, mshape[1,1]=1 --> calculate yy, mshape[1,2]=1 --> calculate xy,
|
||||||
|
by default, xx is calculated.
|
||||||
|
"""
|
||||||
|
if mshape==None:
|
||||||
|
mshape=numpy.zeros(9).reshape(3,3)
|
||||||
|
mshape[0,0]=1
|
||||||
|
assert mshape.shape == (3, 3), "mshape should be 3x3"
|
||||||
|
assert hasattr(self, "Sigma_imp"), "Set Sigma First!"
|
||||||
|
velocities = self.velocities
|
||||||
|
mu = self.chemical_potential
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
print "Chemical_Potential", mu
|
||||||
|
# use k-dependent-projections.
|
||||||
|
assert self.k_dep_projection == 1, "Not implemented!"
|
||||||
|
|
||||||
|
# form self energy from impurity self energy and double counting term.
|
||||||
|
stmp = self.add_dc()
|
||||||
|
|
||||||
|
#set mesh and energy range for spectrals functions
|
||||||
|
# one could construct self energy within only a small energy range when calculating transports.
|
||||||
|
M = [x for x in self.Sigma_imp[0].mesh]
|
||||||
|
N_om = len(M)
|
||||||
|
if energywindow is None:
|
||||||
|
omminplot = M[0].real - 0.001
|
||||||
|
ommaxplot = M[N_om - 1].real + 0.001
|
||||||
|
else:
|
||||||
|
omminplot = energywindow[0]
|
||||||
|
ommaxplot = energywindow[1]
|
||||||
|
# set mesh for Pw, only mesh in focused energyrange is needed. Mpw is just the index of mesh need in M
|
||||||
|
Mpw = [i for i in xrange(len(M)) if (M[i].real > omminplot and M[i].real < ommaxplot)]
|
||||||
|
|
||||||
|
# output P(\omega)_xy should has the same dimension as defined in mshape.
|
||||||
|
self.Pw = numpy.zeros((mshape.sum(), N_om), dtype=numpy.float)
|
||||||
|
|
||||||
|
mlist = []
|
||||||
|
for ir in xrange(3):
|
||||||
|
for ic in xrange(3):
|
||||||
|
if(mshape[ir][ic] == 1):
|
||||||
|
mlist.append((ir, ic))
|
||||||
|
|
||||||
|
ik = 0
|
||||||
|
# will construct G in the end; don't be mislead by
|
||||||
|
# nomenclature; S is sometimes sigma, sometimes sigma^-1, etc.
|
||||||
|
|
||||||
|
|
||||||
|
bln = self.block_names[self.SO]
|
||||||
|
ntoi = self.names_to_ind[self.SO]
|
||||||
|
|
||||||
|
S = BlockGf(name_block_generator=[(bln[isp], GfReFreq(indices=range(self.n_orbitals[ik][isp]), mesh=self.Sigma_imp[0].mesh)) for isp in range(self.Nspinblocs) ], make_copies=False)
|
||||||
|
mupat = [numpy.identity(self.n_orbitals[ik][isp], numpy.complex_) * mu for isp in range(self.Nspinblocs)] # construct mupat
|
||||||
|
Annkw = [numpy.zeros((self.n_orbitals[ik][isp], self.n_orbitals[ik][isp], N_om), dtype=numpy.complex_) for isp in range(self.Nspinblocs)]
|
||||||
|
|
||||||
|
ikarray = numpy.array(range(self.n_k))
|
||||||
|
for ik in myMPI.slice_array(ikarray):
|
||||||
|
|
||||||
|
#for ik in xrange(self.n_k):
|
||||||
|
unchangesize = all([ self.n_orbitals[ik][isp] == mupat[isp].shape[0] for isp in range(self.Nspinblocs)])
|
||||||
|
if (not unchangesize):
|
||||||
|
# recontruct green functions.
|
||||||
|
S = BlockGf(name_block_generator=[(bln[isp], GfReFreq(indices=range(self.n_orbitals[ik][isp]),
|
||||||
|
mesh=self.Sigma_imp[0].mesh))
|
||||||
|
for isp in range(self.Nspinblocs) ],
|
||||||
|
make_copies=False)
|
||||||
|
# change size of mupat
|
||||||
|
mupat = [numpy.identity(self.n_orbitals[ik][isp], numpy.complex_) * mu for isp in range(self.Nspinblocs)] # construct mupat
|
||||||
|
#Annkw=numpy.zeros((self.n_orbitals[ik],self.n_orbitals[ik],N_om),dtype=numpy.complex_)
|
||||||
|
Annkw = [numpy.zeros((self.n_orbitals[ik][isp], self.n_orbitals[ik][isp], N_om), dtype=numpy.complex_) for isp in range(self.Nspinblocs)]
|
||||||
|
# get lattice green functions.
|
||||||
|
# S <<= A_Omega_Plus_B(A=1, B=1j * broadening)
|
||||||
|
|
||||||
|
S <<= 1*Omega+1j*broadening
|
||||||
|
|
||||||
|
Ms = copy.deepcopy(mupat)
|
||||||
|
for ibl in range(self.Nspinblocs):
|
||||||
|
n_orb = self.n_orbitals[ik][ibl]
|
||||||
|
ind = ntoi[bln[ibl]]
|
||||||
|
Ms[ibl] = self.hopping[ik,ind,0:n_orb,0:n_orb].real - mupat[ibl]
|
||||||
|
S -= Ms
|
||||||
|
|
||||||
|
tmp = S.copy()
|
||||||
|
for icrsh in xrange(self.n_corr_shells):
|
||||||
|
for sig, gf in tmp: tmp[sig] <<= self.upfold(ik, icrsh, sig, stmp[icrsh][sig], gf)
|
||||||
|
S -= tmp
|
||||||
|
|
||||||
|
S.invert()
|
||||||
|
|
||||||
|
#hence we have A(k,\omega)_nn' for a special k points.
|
||||||
|
for isp in range(self.Nspinblocs):
|
||||||
|
# Annkw[isp].real = -copy.deepcopy(S[self.block_names[self.SO][isp]]._data.array).imag / numpy.pi
|
||||||
|
Annkw[isp].real = -copy.deepcopy(S[self.block_names[self.SO][isp]].data.swapaxes(0,1).swapaxes(1,2)).imag / numpy.pi
|
||||||
|
|
||||||
|
# A=-1/pi*Im G
|
||||||
|
|
||||||
|
# for different spin velocties might be different
|
||||||
|
for isp in range(self.Nspinblocs):
|
||||||
|
if(ik%100==0):
|
||||||
|
print "ik,isp", ik, isp
|
||||||
|
kvel = velocities[isp].vks[ik]
|
||||||
|
|
||||||
|
# in general, bandwindows for Annkw and for velocities are not the same.
|
||||||
|
# one should make sure the same window are using before go further. otherwise the matrix size are not match.
|
||||||
|
|
||||||
|
Pwtem = numpy.zeros((mshape.sum(), N_om), dtype=numpy.float_)
|
||||||
|
|
||||||
|
#symmetry loop
|
||||||
|
# how to symmetrize this part???
|
||||||
|
for Rmat in self.symm:
|
||||||
|
# get new velocity.
|
||||||
|
Rkvel = copy.deepcopy(kvel.vel)
|
||||||
|
for vnb1 in xrange(kvel.bandwin[1] - kvel.bandwin[0] + 1):
|
||||||
|
for vnb2 in xrange(kvel.bandwin[1] - kvel.bandwin[0] + 1):
|
||||||
|
Rkvel[vnb1][vnb2][:] = numpy.dot(Rmat, Rkvel[vnb1][vnb2][:])
|
||||||
|
ipw = 0
|
||||||
|
bmin = max(self.bandwin[isp][ik, 0], kvel.bandwin[0])
|
||||||
|
bmax = min(self.bandwin[isp][ik, 1], kvel.bandwin[1])
|
||||||
|
Astart = bmin - self.bandwin[isp][ik, 0]
|
||||||
|
Aend = bmax - self.bandwin[isp][ik, 0] + 1
|
||||||
|
vstart = bmin - kvel.bandwin[0]
|
||||||
|
vend = bmax - kvel.bandwin[0] + 1
|
||||||
|
for (ir, ic) in mlist:
|
||||||
|
#for iw in xrange(N_om):
|
||||||
|
for iw in Mpw:
|
||||||
|
#if (M[iw]>omminplot) and (M[iw]<ommaxplot):
|
||||||
|
# here use bandwin to construct match matrix for A and velocity.
|
||||||
|
Annkwt = Annkw[isp][Astart:Aend, Astart:Aend, iw]
|
||||||
|
Rkveltr = Rkvel[vstart:vend, vstart:vend, ir]
|
||||||
|
Rkveltc = Rkvel[vstart:vend, vstart:vend, ic]
|
||||||
|
#print Annkwt.shape,Rkvel[...,ir].shape
|
||||||
|
Pwtem[ipw, iw] += numpy.dot(numpy.dot(numpy.dot(Rkveltr, Annkwt), Rkveltc), Annkwt).trace().real
|
||||||
|
ipw += 1
|
||||||
|
|
||||||
|
# k sum and spin sum.
|
||||||
|
self.Pw += Pwtem * self.bz_weights[ik] / self.nsymm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.Pw = myMPI.all_reduce(myMPI.world, self.Pw, lambda x, y : x + y)
|
||||||
|
# for non-magnetic case, the total weight is doubled because of spin degeneracy.
|
||||||
|
self.Pw *= (2 - self.SP)
|
||||||
|
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
with open("TD_DMFT.dat", "w") as pwout:
|
||||||
|
for iw in xrange(N_om):
|
||||||
|
if (M[iw].real > omminplot) and (M[iw].real < ommaxplot):
|
||||||
|
pwout.write(str(M[iw].real) + " ")
|
||||||
|
for i in range(self.Pw.shape[0]):
|
||||||
|
pwout.write(str(self.Pw[i, iw]) + " ")
|
||||||
|
pwout.write("\n")
|
||||||
|
|
||||||
|
def OpticDistribution(self, wiencase, mshape=None, broadening=0.01, energywindow=None, Qmesh=[0.5], Beta=50, loadpw=False):
|
||||||
|
"""calculate Tr A(k,w) v(k) A(k, w+q) v(k) and optics.
|
||||||
|
energywindow is the regime for omega integral
|
||||||
|
Qmesh contains the frequencies of the optic conductivitity. I repin the Qmesh to the self-energy mesh,
|
||||||
|
so the exact value might not exactly the same as given in the list.
|
||||||
|
|
||||||
|
mshape defines the indices of directions. xx,yy,zz,xy,yz,zx.
|
||||||
|
mshape is 3x3 matrix, mshape[0,0]=1 --> calculate xx, mshape[1,1]=1 --> calculate yy, mshape[1,2]=1 --> calculate xy,
|
||||||
|
by default, xx is calculated.
|
||||||
|
"""
|
||||||
|
assert mshape.shape == (3, 3), "mshape should be 3x3"
|
||||||
|
|
||||||
|
assert hasattr(self, "Sigma_imp"), "Set Sigma First!"
|
||||||
|
assert ((self.SP == 0) and (self.SO == 0)), "For SP and SO implementation of spaghettis has to be changed!"
|
||||||
|
velocities = self.velocities
|
||||||
|
# calculate A(k,w):
|
||||||
|
mu = self.chemical_potential
|
||||||
|
|
||||||
|
#we need this somehow for k_dep_projections. So we have to face the problem that the size of A(k,\omega) will
|
||||||
|
#change, and more, the band index for the A(k,\omega) matrix is not known yet.
|
||||||
|
|
||||||
|
# use k-dependent-projections.
|
||||||
|
assert self.k_dep_projection == 1, "Not implemented!"
|
||||||
|
|
||||||
|
# form self energy from impurity self energy and double counting term.
|
||||||
|
stmp = self.add_dc()
|
||||||
|
|
||||||
|
#set mesh and energyrange.
|
||||||
|
M = [x for x in self.Sigma_imp[0].mesh]
|
||||||
|
deltaM = numpy.abs(M[0] - M[1])
|
||||||
|
N_om = len(M)
|
||||||
|
if energywindow is None:
|
||||||
|
omminplot = M[0].real - 0.001
|
||||||
|
ommaxplot = M[N_om - 1].real + 0.001
|
||||||
|
else:
|
||||||
|
omminplot = energywindow[0]
|
||||||
|
ommaxplot = energywindow[1]
|
||||||
|
|
||||||
|
# define exact mesh for optic conductivity
|
||||||
|
Qmesh_ex = [int(x / deltaM) for x in Qmesh]
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
print "Qmesh ", Qmesh
|
||||||
|
print "mesh interval in self energy ", deltaM
|
||||||
|
print "Qmesh / mesh interval ", Qmesh_ex
|
||||||
|
|
||||||
|
# output P(\omega)_xy should has the same dimension as defined in mshape.
|
||||||
|
self.Pw_optic = numpy.zeros((mshape.sum(), len(Qmesh), N_om), dtype=numpy.float_)
|
||||||
|
|
||||||
|
mlist = []
|
||||||
|
for ir in xrange(3):
|
||||||
|
for ic in xrange(3):
|
||||||
|
if(mshape[ir][ic] == 1):
|
||||||
|
mlist.append((ir, ic))
|
||||||
|
ik = 0
|
||||||
|
|
||||||
|
bln = self.block_names[self.SO]
|
||||||
|
ntoi = self.names_to_ind[self.SO]
|
||||||
|
|
||||||
|
S = BlockGf(name_block_generator=[(bln[isp], GfReFreq(indices=range(self.n_orbitals[ik][isp]),
|
||||||
|
mesh=self.Sigma_imp[0].mesh))
|
||||||
|
for isp in range(self.Nspinblocs) ],
|
||||||
|
make_copies=False)
|
||||||
|
mupat = [numpy.identity(self.n_orbitals[ik][isp], numpy.complex_) * mu for isp in range(self.Nspinblocs)] # construct mupat
|
||||||
|
Annkw = [numpy.zeros((self.n_orbitals[ik][isp], self.n_orbitals[ik][isp], N_om), dtype=numpy.complex_) for isp in range(self.Nspinblocs)]
|
||||||
|
|
||||||
|
ikarray = numpy.array(range(self.n_k))
|
||||||
|
for ik in myMPI.slice_array(ikarray):
|
||||||
|
unchangesize = all([ self.n_orbitals[ik][isp] == mupat[isp].shape[0] for isp in range(self.Nspinblocs)])
|
||||||
|
if (not unchangesize):
|
||||||
|
# recontruct green functions.
|
||||||
|
S = BlockGf(name_block_generator=[(bln[isp], GfReFreq(indices=range(self.n_orbitals[ik][isp]),
|
||||||
|
mesh=self.Sigma_imp[0].mesh))
|
||||||
|
for isp in range(self.Nspinblocs) ],
|
||||||
|
make_copies=False)
|
||||||
|
|
||||||
|
# S = GF(name_block_generator=[ (s, GFBloc_ReFreq(Indices=BS, Mesh=self.Sigma_imp[0].mesh)) for s in ['up', 'down'] ], Copy=False)
|
||||||
|
# mupat = numpy.identity(self.n_orbitals[ik], numpy.complex_) # change size of mupat
|
||||||
|
mupat = [numpy.identity(self.n_orbitals[ik][isp], numpy.complex_) * mu for isp in range(self.Nspinblocs)] # construct mupat
|
||||||
|
# mupat *= mu
|
||||||
|
|
||||||
|
#set a temporary array storing spectral functions with band index. Note, usually we should have spin index
|
||||||
|
#Annkw=numpy.zeros((self.n_orbitals[ik],self.n_orbitals[ik],N_om),dtype=numpy.complex_)
|
||||||
|
Annkw = [numpy.zeros((self.n_orbitals[ik][isp], self.n_orbitals[ik][isp], N_om), dtype=numpy.complex_) for isp in range(self.Nspinblocs)]
|
||||||
|
|
||||||
|
# get lattice green functions.
|
||||||
|
# S <<= A_Omega_Plus_B(A=1, B=1j * broadening)
|
||||||
|
|
||||||
|
S <<= 1*Omega + 1j*broadening
|
||||||
|
|
||||||
|
Ms = copy.deepcopy(mupat)
|
||||||
|
for ibl in range(self.Nspinblocs):
|
||||||
|
ind = ntoi[bln[ibl]]
|
||||||
|
n_orb = self.n_orbitals[ik][ibl]
|
||||||
|
Ms[ibl] = self.hopping[ik,ind,0:n_orb,0:n_orb].real - mupat[ibl]
|
||||||
|
S -= Ms
|
||||||
|
|
||||||
|
tmp = S.copy() # init temporary storage
|
||||||
|
## substract self energy
|
||||||
|
for icrsh in xrange(self.n_corr_shells):
|
||||||
|
for sig, gf in tmp: tmp[sig] <<= self.upfold(ik, icrsh, sig, stmp[icrsh][sig], gf)
|
||||||
|
S -= tmp
|
||||||
|
|
||||||
|
S.invert()
|
||||||
|
|
||||||
|
for isp in range(self.Nspinblocs):
|
||||||
|
Annkw[isp].real = -copy.deepcopy(S[self.block_names[self.SO][isp]].data.swapaxes(0,1).swapaxes(1,2)).imag / numpy.pi
|
||||||
|
|
||||||
|
for isp in range(self.Nspinblocs):
|
||||||
|
if(ik%100==0):
|
||||||
|
print "ik,isp", ik, isp
|
||||||
|
kvel = velocities[isp].vks[ik]
|
||||||
|
|
||||||
|
Pwtem = numpy.zeros((mshape.sum(), len(Qmesh_ex), N_om), dtype=numpy.float_)
|
||||||
|
|
||||||
|
#symmetry loop
|
||||||
|
for Rmat in self.symm:
|
||||||
|
# get new velocity.
|
||||||
|
Rkvel = copy.deepcopy(kvel.vel)
|
||||||
|
for vnb1 in xrange(kvel.bandwin[1] - kvel.bandwin[0] + 1):
|
||||||
|
for vnb2 in xrange(kvel.bandwin[1] - kvel.bandwin[0] + 1):
|
||||||
|
Rkvel[vnb1][vnb2][:] = numpy.dot(Rmat, Rkvel[vnb1][vnb2][:])
|
||||||
|
ipw = 0
|
||||||
|
for (ir, ic) in mlist:
|
||||||
|
for iw in xrange(N_om):
|
||||||
|
|
||||||
|
if(M[iw].real > 5.0 / Beta):
|
||||||
|
continue
|
||||||
|
for iq in range(len(Qmesh_ex)):
|
||||||
|
#if(Qmesh_ex[iq]==0 or iw+Qmesh_ex[iq]>=N_om ):
|
||||||
|
# here use fermi distribution to truncate self energy mesh.
|
||||||
|
if(Qmesh_ex[iq] == 0 or iw + Qmesh_ex[iq] >= N_om
|
||||||
|
or M[iw].real + Qmesh[iq] < -10.0 / Beta or M[iw].real >10.0 / Beta):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (M[iw].real > omminplot) and (M[iw].real < ommaxplot):
|
||||||
|
# here use bandwin to construct match matrix for A and velocity.
|
||||||
|
bmin = max(self.bandwin[isp][ik, 0], kvel.bandwin[0])
|
||||||
|
bmax = min(self.bandwin[isp][ik, 1], kvel.bandwin[1])
|
||||||
|
Astart = bmin - self.bandwin[isp][ik, 0]
|
||||||
|
Aend = bmax - self.bandwin[isp][ik, 0] + 1
|
||||||
|
vstart = bmin - kvel.bandwin[0]
|
||||||
|
vend = bmax - kvel.bandwin[0] + 1
|
||||||
|
Annkwl = Annkw[isp][Astart:Aend, Astart:Aend, iw]
|
||||||
|
Annkwr = Annkw[isp][Astart:Aend, Astart:Aend, iw + Qmesh_ex[iq]]
|
||||||
|
Rkveltr = Rkvel[vstart:vend, vstart:vend, ir]
|
||||||
|
Rkveltc = Rkvel[vstart:vend, vstart:vend, ic]
|
||||||
|
#print Annkwt.shape,Rkvel[...,ir].shape
|
||||||
|
Pwtem[ipw, iq, iw] += numpy.dot(numpy.dot(numpy.dot(Rkveltr, Annkwl), Rkveltc), Annkwr).trace().real
|
||||||
|
ipw += 1
|
||||||
|
|
||||||
|
# k sum and spin sum.
|
||||||
|
self.Pw_optic += Pwtem * self.bz_weights[ik] / self.nsymm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.Pw_optic = myMPI.all_reduce(myMPI.world, self.Pw_optic, lambda x, y : x + y)
|
||||||
|
self.Pw_optic *= (2 - self.SP)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# just back up TD_optic data
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
with open("TD_Optic_DMFT.dat", "w") as pwout:
|
||||||
|
#shape
|
||||||
|
L1,L2,L3=self.Pw_optic.shape
|
||||||
|
pwout.write("%s %s %s\n"%(L1,L2,L3))
|
||||||
|
#dump Qmesh
|
||||||
|
Qmeshr=[i*deltaM for i in Qmesh_ex]
|
||||||
|
#dump self energy mesh
|
||||||
|
#dump Pw_optic
|
||||||
|
for iq in xrange(L2):
|
||||||
|
pwout.write(str(Qmeshr[iq])+" ")
|
||||||
|
pwout.write("\n")
|
||||||
|
for iw in xrange(L3):
|
||||||
|
pwout.write(str(M[iw].real)+" ")
|
||||||
|
pwout.write("\n")
|
||||||
|
for i in xrange(L1):
|
||||||
|
for iq in xrange(L2):
|
||||||
|
for iw in xrange(L3):
|
||||||
|
pwout.write(str(self.Pw_optic[i, iq, iw]) + " ")
|
||||||
|
pwout.write("\n")
|
||||||
|
|
||||||
|
# sum over omega to get optic conductivity for ik in xrange(self
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
OpticConductivity = numpy.zeros((mshape.sum(), len(Qmesh)), dtype=numpy.float_)
|
||||||
|
for im in range(mshape.sum()):
|
||||||
|
for iq in range(len(Qmesh)):
|
||||||
|
for iw in xrange(N_om):
|
||||||
|
omegaT = M[iw].real * Beta
|
||||||
|
omega_aug = Qmesh_ex[iq] * deltaM
|
||||||
|
OpticConductivity[im, iq] += self.Pw_optic[im, iq, iw] * (fermidis(omegaT) - fermidis(omegaT + omega_aug * Beta)) / omega_aug
|
||||||
|
OpticConductivity *= deltaM
|
||||||
|
OpticConductivity *= 10700 / self.Vol
|
||||||
|
with open("Optic_con.dat", "wOptic_con") as opt:
|
||||||
|
for iq in range(len(Qmesh_ex)):
|
||||||
|
opt.write(str(Qmesh_ex[iq] * deltaM) + " ")
|
||||||
|
for im in range(mshape.sum()):
|
||||||
|
opt.write(str(OpticConductivity[im, iq]) + " ")
|
||||||
|
opt.write("\n")
|
||||||
|
|
||||||
|
def loadOpticTD(self,OpticTDFile="TD_Optic_DMFT.dat",Beta=40):
|
||||||
|
""" load optic conductivity distribution and calculate Optical Conductivty
|
||||||
|
"""
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
with open(OpticTDFile,"r") as pw:
|
||||||
|
L1,L2,L3=(int(i) for i in pw.readline().split())
|
||||||
|
#QMeshr=numpy.zeros(L2,dtype=numpy.float)
|
||||||
|
#M=numpy.zeros(L3,dtype=numpy.float)
|
||||||
|
#Pw_optic=numpy.zeros((L1,L2,L3), dtype=numpy.float)
|
||||||
|
|
||||||
|
QMeshr=numpy.array([float(i) for i in pw.readline().split()])
|
||||||
|
M=numpy.array([float(i) for i in pw.readline().split()])
|
||||||
|
Pw_optic=numpy.array([float(i) for i in pw.readline().split()]).reshape(L1,L2,L3)
|
||||||
|
|
||||||
|
OpticConductivity = numpy.zeros((L1, L2), dtype=numpy.float)
|
||||||
|
deltaM=M[1]-M[0]
|
||||||
|
for im in xrange(L1):
|
||||||
|
for iq in xrange(L2):
|
||||||
|
for iw in xrange(L3):
|
||||||
|
omegaT = M[iw] * Beta
|
||||||
|
omega_aug = QMeshr[iq]
|
||||||
|
OpticConductivity[im, iq] += Pw_optic[im, iq, iw] * (fermidis(omegaT) - fermidis(omegaT + omega_aug * Beta)) / omega_aug
|
||||||
|
OpticConductivity *= deltaM
|
||||||
|
## transform to standard unit as in resistivity
|
||||||
|
OpticConductivity *= 10700 / self.Vol
|
||||||
|
##
|
||||||
|
with open("Optic_con.dat", "w") as opt:
|
||||||
|
for iq in xrange(L2):
|
||||||
|
opt.write(str(QMeshr[iq]) + " ")
|
||||||
|
for im in xrange(L1):
|
||||||
|
opt.write(str(OpticConductivity[im, iq]) + " ")
|
||||||
|
opt.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def OpticDistribution_LDA(self, wiencase, mshape=None, broadening=0.01, energywindow=None, Qmesh=[0.5], Beta=50, loadpw=False):
|
||||||
|
"""calculate Tr A(k,w) v(k) A(k, w+q) v(k) and optics. A constant self-energy is used to mimick noninteracting case.
|
||||||
|
It is not the best way to calculate optic for LDA. Just to compare.
|
||||||
|
energywindow is the regime for omega integral
|
||||||
|
Qmesh contains the frequencies of the optic conductivitity. I repin the Qmesh to the self-energy mesh,
|
||||||
|
so the exact value might not exactly the same as given in the list.
|
||||||
|
|
||||||
|
mshape defines the indices of directions. xx,yy,zz,xy,yz,zx.
|
||||||
|
mshape is 3x3 matrix, mshape[0,0]=1 --> calculate xx, mshape[1,1]=1 --> calculate yy, mshape[1,2]=1 --> calculate xy,
|
||||||
|
by default, xx is calculated.
|
||||||
|
"""
|
||||||
|
assert mshape.shape == (3, 3), "mshape should be 3x3"
|
||||||
|
|
||||||
|
assert hasattr(self, "Sigma_imp"), "Set Sigma First!"
|
||||||
|
assert ((self.SP == 0) and (self.SO == 0)), "For SP and SO implementation of spaghettis has to be changed!"
|
||||||
|
velocities = self.velocities
|
||||||
|
# calculate A(k,w):
|
||||||
|
mu = self.chemical_potential
|
||||||
|
|
||||||
|
#we need this somehow for k_dep_projections. So we have to face the problem that the size of A(k,\omega) will
|
||||||
|
#change, and more, the band index for the A(k,\omega) matrix is not known yet.
|
||||||
|
|
||||||
|
# use k-dependent-projections.
|
||||||
|
assert self.k_dep_projection == 1, "Not implemented!"
|
||||||
|
|
||||||
|
# form self energy from impurity self energy and double counting term.
|
||||||
|
stmp = self.add_dc()
|
||||||
|
|
||||||
|
#set mesh and energyrange.
|
||||||
|
M = [x for x in self.Sigma_imp[0].mesh]
|
||||||
|
deltaM = numpy.abs(M[0] - M[1])
|
||||||
|
N_om = len(M)
|
||||||
|
if energywindow is None:
|
||||||
|
omminplot = M[0] - 0.001
|
||||||
|
ommaxplot = M[N_om - 1] + 0.001
|
||||||
|
else:
|
||||||
|
omminplot = energywindow[0]
|
||||||
|
ommaxplot = energywindow[1]
|
||||||
|
|
||||||
|
# define exact mesh for optic conductivity
|
||||||
|
Qmesh_ex = [int(x / deltaM) for x in Qmesh]
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
print "Qmesh ", Qmesh
|
||||||
|
print "mesh interval in self energy ", deltaM
|
||||||
|
print "Qmesh / mesh interval ", Qmesh_ex
|
||||||
|
|
||||||
|
# output P(\omega)_xy should has the same dimension as defined in mshape.
|
||||||
|
self.Pw_optic = numpy.zeros((mshape.sum(), len(Qmesh), N_om), dtype=numpy.float_)
|
||||||
|
|
||||||
|
mlist = []
|
||||||
|
for ir in xrange(3):
|
||||||
|
for ic in xrange(3):
|
||||||
|
if(mshape[ir][ic] == 1):
|
||||||
|
mlist.append((ir, ic))
|
||||||
|
ik = 0
|
||||||
|
|
||||||
|
bln = self.block_names[self.SO]
|
||||||
|
ntoi = self.names_to_ind[self.SO]
|
||||||
|
|
||||||
|
S = BlockGf(name_block_generator=[(bln[isp], GfReFreq(indices=range(self.n_orbitals[ik][isp]),
|
||||||
|
mesh=self.Sigma_imp[0].mesh))
|
||||||
|
for isp in range(self.Nspinblocs) ],
|
||||||
|
make_copies=False)
|
||||||
|
mupat = [numpy.identity(self.n_orbitals[ik][isp], numpy.complex_) * mu for isp in range(self.Nspinblocs)] # construct mupat
|
||||||
|
Annkw = [numpy.zeros((self.n_orbitals[ik][isp], self.n_orbitals[ik][isp], N_om), dtype=numpy.complex_) for isp in range(self.Nspinblocs)]
|
||||||
|
|
||||||
|
ikarray = numpy.array(range(self.n_k))
|
||||||
|
for ik in myMPI.slice_array(ikarray):
|
||||||
|
unchangesize = all([ self.n_orbitals[ik][isp] == mupat[isp].shape[0] for isp in range(self.Nspinblocs)])
|
||||||
|
if (not unchangesize):
|
||||||
|
# recontruct green functions.
|
||||||
|
S = BlockGf(name_block_generator=[(bln[isp], GfReFreq(indices=range(self.n_orbitals[ik][isp]),
|
||||||
|
mesh=self.Sigma_imp[0].mesh))
|
||||||
|
for isp in range(self.Nspinblocs) ],
|
||||||
|
make_copies=False)
|
||||||
|
|
||||||
|
# S = GF(name_block_generator=[ (s, GFBloc_ReFreq(Indices=BS, Mesh=self.Sigma_imp[0].mesh)) for s in ['up', 'down'] ], Copy=False)
|
||||||
|
# mupat = numpy.identity(self.n_orbitals[ik], numpy.complex_) # change size of mupat
|
||||||
|
mupat = [numpy.identity(self.n_orbitals[ik][isp], numpy.complex_) * mu for isp in range(self.Nspinblocs)] # construct mupat
|
||||||
|
# mupat *= mu
|
||||||
|
|
||||||
|
#set a temporary array storing spectral functions with band index. Note, usually we should have spin index
|
||||||
|
#Annkw=numpy.zeros((self.n_orbitals[ik],self.n_orbitals[ik],N_om),dtype=numpy.complex_)
|
||||||
|
Annkw = [numpy.zeros((self.n_orbitals[ik][isp], self.n_orbitals[ik][isp], N_om), dtype=numpy.complex_) for isp in range(self.Nspinblocs)]
|
||||||
|
|
||||||
|
# get lattice green functions.
|
||||||
|
# S <<= A_Omega_Plus_B(A=1, B=1j * broadening)
|
||||||
|
|
||||||
|
S <<= 1*Omega + 1j*broadening
|
||||||
|
|
||||||
|
Ms = copy.deepcopy(mupat)
|
||||||
|
for ibl in range(self.Nspinblocs):
|
||||||
|
ind = ntoi[bln[ibl]]
|
||||||
|
n_orb = self.n_orbitals[ik][ibl]
|
||||||
|
Ms[ibl] = self.hopping[ik,ind,0:n_orb,0:n_orb].real - mupat[ibl]
|
||||||
|
S -= Ms
|
||||||
|
# tmp = S.copy() # init temporary storage
|
||||||
|
# ## substract self energy
|
||||||
|
# for icrsh in xrange(self.n_corr_shells):
|
||||||
|
# for sig, gf in tmp: tmp[sig] <<= self.upfold(ik, icrsh, sig, stmp[icrsh][sig], gf)
|
||||||
|
# S -= tmp
|
||||||
|
|
||||||
|
S.invert()
|
||||||
|
|
||||||
|
for isp in range(self.Nspinblocs):
|
||||||
|
Annkw[isp].real = -copy.deepcopy(S[self.block_names[self.SO][isp]].data.swapaxes(0,1).swapaxes(1,2)).imag / numpy.pi
|
||||||
|
|
||||||
|
for isp in range(self.Nspinblocs):
|
||||||
|
if(ik%100==0):
|
||||||
|
print "ik,isp", ik, isp
|
||||||
|
kvel = velocities[isp].vks[ik]
|
||||||
|
|
||||||
|
Pwtem = numpy.zeros((mshape.sum(), len(Qmesh_ex), N_om), dtype=numpy.float_)
|
||||||
|
|
||||||
|
#symmetry loop
|
||||||
|
for Rmat in self.symm:
|
||||||
|
# get new velocity.
|
||||||
|
Rkvel = copy.deepcopy(kvel.vel)
|
||||||
|
for vnb1 in xrange(kvel.bandwin[1] - kvel.bandwin[0] + 1):
|
||||||
|
for vnb2 in xrange(kvel.bandwin[1] - kvel.bandwin[0] + 1):
|
||||||
|
Rkvel[vnb1][vnb2][:] = numpy.dot(Rmat, Rkvel[vnb1][vnb2][:])
|
||||||
|
ipw = 0
|
||||||
|
for (ir, ic) in mlist:
|
||||||
|
for iw in xrange(N_om):
|
||||||
|
if(M[iw].real > 5.0 / Beta):
|
||||||
|
continue
|
||||||
|
for iq in range(len(Qmesh_ex)):
|
||||||
|
#if(Qmesh_ex[iq]==0 or iw+Qmesh_ex[iq]>=N_om ):
|
||||||
|
# here use fermi distribution to truncate self energy mesh.
|
||||||
|
if(Qmesh_ex[iq] == 0 or iw + Qmesh_ex[iq] >= N_om
|
||||||
|
or M[iw].real + Qmesh[iq] < -10.0 / Beta or M[iw].real >10.0 / Beta):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (M[iw].real > omminplot) and (M[iw].real < ommaxplot):
|
||||||
|
# here use bandwin to construct match matrix for A and velocity.
|
||||||
|
bmin = max(self.bandwin[isp][ik, 0], kvel.bandwin[0])
|
||||||
|
bmax = min(self.bandwin[isp][ik, 1], kvel.bandwin[1])
|
||||||
|
Astart = bmin - self.bandwin[isp][ik, 0]
|
||||||
|
Aend = bmax - self.bandwin[isp][ik, 0] + 1
|
||||||
|
vstart = bmin - kvel.bandwin[0]
|
||||||
|
vend = bmax - kvel.bandwin[0] + 1
|
||||||
|
Annkwl = Annkw[isp][Astart:Aend, Astart:Aend, iw]
|
||||||
|
Annkwr = Annkw[isp][Astart:Aend, Astart:Aend, iw + Qmesh_ex[iq]]
|
||||||
|
Rkveltr = Rkvel[vstart:vend, vstart:vend, ir]
|
||||||
|
Rkveltc = Rkvel[vstart:vend, vstart:vend, ic]
|
||||||
|
#print Annkwt.shape,Rkvel[...,ir].shape
|
||||||
|
Pwtem[ipw, iq, iw] += numpy.dot(numpy.dot(numpy.dot(Rkveltr, Annkwl), Rkveltc), Annkwr).trace().real
|
||||||
|
ipw += 1
|
||||||
|
|
||||||
|
# k sum and spin sum.
|
||||||
|
self.Pw_optic += Pwtem * self.bz_weights[ik] / self.nsymm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.Pw_optic = myMPI.all_reduce(myMPI.world, self.Pw_optic, lambda x, y : x + y)
|
||||||
|
self.Pw_optic *= (2 - self.SP)
|
||||||
|
|
||||||
|
|
||||||
|
# just back up TD_optic data # just back up TD_optic data
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
with open("TD_Optic_LDA.dat", "w") as pwout:
|
||||||
|
L1,L2,L3=self.Pw_optic.shape
|
||||||
|
pwout.write("%s %s %s\n"%(L1,L2,L3))
|
||||||
|
for i in xrange(L1):
|
||||||
|
for iq in xrange(L2):
|
||||||
|
for iw in xrange(L3):
|
||||||
|
pwout.write(str(i)+" "+str(Qmesh_ex[iq] * deltaM) + " " + str(M[iw]) + " ")
|
||||||
|
pwout.write(str(self.Pw_optic[i, iq, iw]) + " ")
|
||||||
|
pwout.write("\n")
|
||||||
|
pwout.write("\n")
|
||||||
|
|
||||||
|
# sum over omega to get optic conductivity
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
OpticConductivity = numpy.zeros((mshape.sum(), len(Qmesh)), dtype=numpy.float_)
|
||||||
|
for im in range(mshape.sum()):
|
||||||
|
for iq in range(len(Qmesh)):
|
||||||
|
for iw in xrange(N_om):
|
||||||
|
omegaT = M[iw] * Beta
|
||||||
|
omega_aug = Qmesh_ex[iq] * deltaM
|
||||||
|
OpticConductivity[im, iq] += self.Pw_optic[im, iq, iw] * (fermidis(omegaT) - fermidis(omegaT + omega_aug * Beta)) / omega_aug
|
||||||
|
OpticConductivity *= deltaM
|
||||||
|
OpticConductivity *= 10700 / self.Vol
|
||||||
|
with open("Optic_con_LDA.dat", "w") as opt:
|
||||||
|
for iq in range(len(Qmesh_ex)):
|
||||||
|
opt.write(str(Qmesh_ex[iq] * deltaM) + " ")
|
||||||
|
for im in range(mshape.sum()):
|
||||||
|
opt.write(str(OpticConductivity[im, iq]) + " ")
|
||||||
|
opt.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
# load transportdistribution Pw from file.
|
||||||
|
def loadTD(self, filename, fermishift=0.0):
|
||||||
|
""" load transport distribution from file. Assume energy mesh is uniform
|
||||||
|
the first column is energy mesh. The others are TD values.
|
||||||
|
fermishift is used to shift the TD mesh to mimick a rigid band shift.
|
||||||
|
"""
|
||||||
|
myMPI.barrier()
|
||||||
|
self.TD = numpy.loadtxt(filename)
|
||||||
|
self.TD[:, 0] -= fermishift
|
||||||
|
|
||||||
|
|
||||||
|
# seebeck is just intetral of omega \int Pw f(\omega)f(-\omega)(\beta w).
|
||||||
|
def Seebeck(self, Beta, index=0):
|
||||||
|
""" get -A1/A0, that is Seebeck in unit k_B/e. index is used to select the column in self.tdintegral.
|
||||||
|
Note: for nodiagonal element in Sxy this might not be right. so take care.
|
||||||
|
"""
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
print "A0, A1 %.5e %.5e " % (self.tdintegral(Beta, 0)[index], self.tdintegral(Beta, 1)[index])
|
||||||
|
seb = -self.tdintegral(Beta, 1)[index] / self.tdintegral(Beta, 0)[index]
|
||||||
|
print "Seebeck%d %.4f k_B/e %.4f x 10^(-6)V/K" % (index, seb, seb * 86.17)
|
||||||
|
return seb
|
||||||
|
|
||||||
|
def Conductivity(self, Beta, index=0):
|
||||||
|
""" #return 1/T*A0, that is Conductivity in unit 1/V
|
||||||
|
return Conductivity
|
||||||
|
"""
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
Cond = Beta * self.tdintegral(Beta, 0)[index]
|
||||||
|
#print "Beta*A0 ", Cond
|
||||||
|
print "V in bohr^3 ", self.Vol
|
||||||
|
Cond *= 10700.0 / self.Vol
|
||||||
|
print "Conductivity%d %.4f x 10^4 Ohm^-1 cm^-1" % (index, Cond)
|
||||||
|
print "Resistivity%d %.4f x 10^-4 Ohm cm" % (index, 1.0 / Cond)
|
||||||
|
return Cond
|
||||||
|
|
||||||
|
def tdintegral(self, Beta, pn=0):
|
||||||
|
"""calculate { \pi *\int Pw f(omega)f(-omega)(\beta\omega)^(pn)d\omega }
|
||||||
|
"""
|
||||||
|
M = self.TD[:, 0]
|
||||||
|
domega = abs(M[1] - M[0])
|
||||||
|
pwint = numpy.zeros(self.TD.shape[1] - 1)
|
||||||
|
for ipw in range(self.TD.shape[1] - 1):
|
||||||
|
for iw in xrange(len(M)):
|
||||||
|
x = M[iw] * Beta
|
||||||
|
pwint[ipw] += fermidis(x) * fermidis(-x) * self.TD[iw, ipw + 1] * numpy.float(x) ** pn * domega
|
||||||
|
|
||||||
|
return pwint
|
||||||
|
|
||||||
|
|
||||||
|
def tdintcore(self, Beta):
|
||||||
|
"""calculate { Pw f(omega)f(-omega) for check data)
|
||||||
|
"""
|
||||||
|
M = self.TD[:, 0]
|
||||||
|
domega = abs(M[1] - M[0])
|
||||||
|
pwint = numpy.zeros((self.TD.shape[1] - 1, M.size))
|
||||||
|
for ipw in range(self.TD.shape[1] - 1):
|
||||||
|
for iw in xrange(M.size):
|
||||||
|
x = M[iw] * Beta
|
||||||
|
pwint[ipw, iw] = self.TD[iw, ipw + 1] * fermidis(x) * fermidis(-x)
|
||||||
|
#if(pwint[ipw,iw]>=0.3):
|
||||||
|
# self.Pw[ipw,iw]=0.0
|
||||||
|
|
||||||
|
if myMPI.is_master_node():
|
||||||
|
with open("tdintcore.dat", "w") as pwout:
|
||||||
|
for iw in xrange(M.size):
|
||||||
|
pwout.write(str(M[iw]) + " ")
|
||||||
|
for i in range(pwint.shape[0]):
|
||||||
|
pwout.write(str(pwint[i, iw]) + " ")
|
||||||
|
pwout.write("\n")
|
||||||
|
return pwint
|
||||||
|
|
||||||
|
|
||||||
|
def bandwinfromwiencase(self, wiencase):
|
||||||
|
""" read in the band window from wiencase.outbwin file.
|
||||||
|
"""
|
||||||
|
bandwin = [numpy.zeros(self.n_k * 2, dtype=int).reshape(self.n_k, 2) for isp in range(self.SP + 1 - self.SO)]
|
||||||
|
for isp in range(self.SP + 1 - self.SO):
|
||||||
|
if(self.SP == 0 or self.SO == 1):
|
||||||
|
winfile = Read_Fortran_File2(wiencase + ".oubwin")
|
||||||
|
elif self.SP == 1 and isp == 0:
|
||||||
|
winfile = Read_Fortran_File2(wiencase + ".oubwinup")
|
||||||
|
elif self.SP == 1 and isp == 1:
|
||||||
|
winfile = Read_Fortran_File2(wiencase + ".oubwindn")
|
||||||
|
else:
|
||||||
|
assert 0, "Reading bandwin error! Check self.SP and self.SO!"
|
||||||
|
Nk = int(winfile.next())
|
||||||
|
assert Nk == self.n_k, "Number of K points is unconsistent in case.oubwin"
|
||||||
|
SO = int(winfile.next())
|
||||||
|
assert SO == self.SO, "SO is unconsistent in case.oubwin"
|
||||||
|
|
||||||
|
for i in xrange(self.n_k):
|
||||||
|
winfile.next()
|
||||||
|
bandwin[isp][i, 0] = winfile.next()
|
||||||
|
bandwin[isp][i, 1] = winfile.next()
|
||||||
|
winfile.next()
|
||||||
|
return bandwin
|
||||||
|
|
431
python/SumK_LDA_Transport_Wien2k_input.py
Normal file
431
python/SumK_LDA_Transport_Wien2k_input.py
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
#
|
||||||
|
# Copyright (C) 2011 by M. Aichhorn, L. Pourovskii, V. Vildosola
|
||||||
|
#
|
||||||
|
# TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
# terms of the GNU General Public License as published by the Free Software
|
||||||
|
# Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
# version.
|
||||||
|
#
|
||||||
|
# TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
#=======================================================================================================================
|
||||||
|
# #################################################################
|
||||||
|
# Code for Transport/Optic calculations based on SumK_LDA... class
|
||||||
|
# by Xiaoyu Deng <xiaoyu.deng@gmail.com>
|
||||||
|
# The code read in files needed for transport/Optic calculations from Wien outputs.
|
||||||
|
# including: symmetry, velocity, lattice constants.
|
||||||
|
# The HDF convention is not adopted here since momentum file from Wien output is usually quite large
|
||||||
|
# and it is not necessary to keep in in the HDF file.
|
||||||
|
# #################################################################
|
||||||
|
#=======================================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
import numpy, sys, os.path
|
||||||
|
|
||||||
|
def Read_Fortran_File (filename):
|
||||||
|
""" Returns a generator that yields all numbers in the Fortran file as float, one by one"""
|
||||||
|
import os.path
|
||||||
|
if not(os.path.exists(filename)) : raise IOError, "File %s does not exists" % filename
|
||||||
|
for line in open(filename, 'r') :
|
||||||
|
for x in line.replace('D', 'E').split() :
|
||||||
|
yield string.atof(x)
|
||||||
|
|
||||||
|
class Velocity_k:
|
||||||
|
"""momentum matrix for a single k points.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self.kp = [0.0, 0.0, 0.0]
|
||||||
|
self.bandwin = [999, 0]
|
||||||
|
# here a matrix for 3 vels. use list since the size of vel is to be determined.
|
||||||
|
self.vel = []
|
||||||
|
|
||||||
|
|
||||||
|
class Velocities:
|
||||||
|
"""Class containig the velocities.
|
||||||
|
Provides container for velocities
|
||||||
|
as a function of k and method to read them from case.pmat Wien2k file
|
||||||
|
use as ClassInstance.vks[ik].vel[iband][jband][ix]
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, wiencase, spinbl=""):
|
||||||
|
if not(os.path.exists(wiencase + ".pmat" + spinbl)) : raise IOError, "File %s does not exists" % wiencase + ".pmat"
|
||||||
|
|
||||||
|
# expected format:
|
||||||
|
# k nu nu2 (k denotes k-point, nu1 starting band index, nu2 ending band index
|
||||||
|
# kpos ( read in if needed.
|
||||||
|
# (real, im) (of velocity for all nu <=nu_prime within nu1 and nu2)
|
||||||
|
# ... ...
|
||||||
|
# k nu nu2
|
||||||
|
# ...
|
||||||
|
f = open(wiencase + ".pmat" + spinbl)
|
||||||
|
self.vks = []
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
s = f.readline()
|
||||||
|
if (s == ""):
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
break
|
||||||
|
try:
|
||||||
|
vec = Velocity_k()
|
||||||
|
[k, nu1, nu2] = [int (x) for x in s.strip().split()]
|
||||||
|
vec.bandwin[0] = nu1
|
||||||
|
vec.bandwin[1] = nu2
|
||||||
|
|
||||||
|
vec.kp = f.readline().strip().split()
|
||||||
|
dim = vec.bandwin[1] - vec.bandwin[0] + 1
|
||||||
|
shape = (dim, dim, 3)
|
||||||
|
vxyz = numpy.zeros(shape, dtype=complex)
|
||||||
|
for nu in xrange(dim):
|
||||||
|
for nu_prime in xrange(nu, dim):
|
||||||
|
for i in xrange(3):
|
||||||
|
s = f.readline().strip("\n ()").split(',')
|
||||||
|
vxyz[nu][nu_prime][i] = float(s[0]) + float(s[1]) * 1j
|
||||||
|
if(nu_prime != nu):
|
||||||
|
vxyz[nu_prime][nu][i] = vxyz[nu][nu_prime][i].conjugate()
|
||||||
|
|
||||||
|
vec.vel = vxyz
|
||||||
|
self.vks.append(vec)
|
||||||
|
|
||||||
|
except IOError:
|
||||||
|
print("Reading case.pmat error. Wrong format?\n ")
|
||||||
|
raise
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
|
def getvel(self, k):
|
||||||
|
# should return array at a given k. use as [iband][jband][i]
|
||||||
|
return self.vks[k].vel
|
||||||
|
|
||||||
|
def plot(self):
|
||||||
|
f = open("velband.dat", "w")
|
||||||
|
bandid = numpy.array([vk.bandwin for vk in self.vks]).flatten()
|
||||||
|
minb = bandid.min()
|
||||||
|
maxb = bandid.max()
|
||||||
|
for ib in range(minb, maxb + 1):
|
||||||
|
ik = 0
|
||||||
|
for vk in self.vks:
|
||||||
|
if(vk.bandwin[0] <= ib and vk.bandwin[1] >= ib):
|
||||||
|
f.write(str(ik) + " ")
|
||||||
|
for i in range(3):
|
||||||
|
f.write(str(vk.vel[ib - vk.bandwin[0]][ib - vk.bandwin[0]][i].real) + " ")
|
||||||
|
f.write("\n")
|
||||||
|
ik = ik + 1
|
||||||
|
f.write("&\n")
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
|
class SGsymmetry():
|
||||||
|
""" read in symmetry of space group from wiencase.outputs other than wiencase.struct since
|
||||||
|
in this file there are also symmetry operations in xyz coordinates..
|
||||||
|
"""
|
||||||
|
def __init__(self, wiencase):
|
||||||
|
structfile = wiencase + ".outputs"
|
||||||
|
self.nsymm = 1
|
||||||
|
self.symm = []
|
||||||
|
self.tau = []
|
||||||
|
self.bravaismatrix = numpy.zeros((3, 3), dtype=numpy.float_)
|
||||||
|
self.symmcartesian = []
|
||||||
|
self.taucartesian = []
|
||||||
|
with open(structfile, "r") as f:
|
||||||
|
f.readline()
|
||||||
|
f.readline()# bravais matrix
|
||||||
|
for i in range(3):
|
||||||
|
line = f.readline().strip().split()
|
||||||
|
self.bravaismatrix[i, :] = numpy.array([numpy.float(item) for item in line])[:]
|
||||||
|
print "bravais matrix", self.bravaismatrix
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
s = f.readline().strip(" ").split()
|
||||||
|
try:
|
||||||
|
if(s[0] == "PGBSYM:"):
|
||||||
|
self.nsymm = int(s[-1])
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
f.readline()
|
||||||
|
f.readline()
|
||||||
|
for i in range(self.nsymm):
|
||||||
|
f.readline()
|
||||||
|
## read symmcartesian
|
||||||
|
symmt = numpy.zeros((3, 3), dtype=float)
|
||||||
|
taut = numpy.zeros((3), dtype=float)
|
||||||
|
for ir in range(3):
|
||||||
|
s = f.readline().strip().split()
|
||||||
|
for ic in range(3):
|
||||||
|
symmt[ir, ic] = float(s[ic])
|
||||||
|
s = f.readline().strip().split()
|
||||||
|
for ir in range(3):
|
||||||
|
taut[ir] = float(s[ir])
|
||||||
|
|
||||||
|
self.symmcartesian.append(symmt)
|
||||||
|
self.taucartesian.append(taut)
|
||||||
|
|
||||||
|
##read symm
|
||||||
|
symmt = numpy.zeros((3, 3), dtype=float)
|
||||||
|
taut = numpy.zeros((3), dtype=float)
|
||||||
|
for ir in range(3):
|
||||||
|
s = f.readline().strip().split()
|
||||||
|
for ic in range(3):
|
||||||
|
symmt[ir, ic] = float(s[ic])
|
||||||
|
taut[ir] = float(s[3])
|
||||||
|
|
||||||
|
self.symm.append(symmt)
|
||||||
|
self.tau.append(taut)
|
||||||
|
|
||||||
|
f.readline()
|
||||||
|
# end
|
||||||
|
f.close()
|
||||||
|
print "Read wiencase.outputs done!"
|
||||||
|
|
||||||
|
def checksymmxyz(self):
|
||||||
|
''' This is to check symm in cartesian coordinates and in primitive cell lattice
|
||||||
|
For details of symm, one should check wien/SRC_symmetry/, latsym.f, pglsym.f,pgbsym.f
|
||||||
|
In general, if a lattice is orthorhombic, then symmcartesian is the same as symmprimitive
|
||||||
|
(at most different by a transpose (or inversion)). If a lattice is not orthorhombic, these two symms could
|
||||||
|
be related by bravais matrix.
|
||||||
|
One special case is CXZ lattice. In Wien CXZ lattice contains two cases: orthorhombic, and
|
||||||
|
monoclinic (with only gamma not equal to 90). For CXZ lattice monoclinic, symmcartesian is also the same as
|
||||||
|
symmprimitive (or with transpose (or inversion)).
|
||||||
|
'''
|
||||||
|
for i in range(self.nsymm):
|
||||||
|
mat = self.symmcartesian[i].transpose() # according to wien2k, why?
|
||||||
|
bm = self.bravaismatrix
|
||||||
|
bminv = numpy.linalg.inv(bm)#.transpose()
|
||||||
|
res = numpy.dot(bminv, numpy.dot(mat, bm)) - self.symm[i]
|
||||||
|
print i, res
|
||||||
|
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return self.nsymm
|
||||||
|
|
||||||
|
def cellvolume(latticetype, latticeconstants, latticeangle):
|
||||||
|
""" calculate cell volume: volumecc conventional cell, volumepc, primitive cell.
|
||||||
|
"""
|
||||||
|
for i in range(3):
|
||||||
|
latticeangle[i] *= 1.0 / 180 * numpy.pi
|
||||||
|
a = latticeconstants[0]
|
||||||
|
b = latticeconstants[1]
|
||||||
|
c = latticeconstants[2]
|
||||||
|
c_al = numpy.cos(latticeangle[0])
|
||||||
|
c_be = numpy.cos(latticeangle[1])
|
||||||
|
c_ga = numpy.cos(latticeangle[2])
|
||||||
|
volumecc = a * b * c * numpy.sqrt(1 + 2 * c_al * c_be * c_ga - c_al ** 2 - c_be * 82 - c_ga ** 2)
|
||||||
|
|
||||||
|
det = {"P":1,
|
||||||
|
"F":4,
|
||||||
|
"B":2,
|
||||||
|
"R":3,
|
||||||
|
"H":1,
|
||||||
|
"CXY":2,
|
||||||
|
"CYZ":2,
|
||||||
|
"CXZ":2
|
||||||
|
}
|
||||||
|
volumepc = volumecc / det[latticetype]
|
||||||
|
|
||||||
|
return volumecc, volumepc
|
||||||
|
|
||||||
|
|
||||||
|
class WienStruct():
|
||||||
|
""" parsing Wien Struct file
|
||||||
|
"""
|
||||||
|
def __init__(self, wiencase):
|
||||||
|
structfile = wiencase + ".struct"
|
||||||
|
|
||||||
|
with open(structfile, "r") as infile:
|
||||||
|
print "read in Wien case file %s" % structfile
|
||||||
|
infile.readline()#title
|
||||||
|
|
||||||
|
tem = infile.readline() #lattice
|
||||||
|
self.latticetype = tem[0:10].split()[0]
|
||||||
|
self.ineqvsite = int(tem[27:30])
|
||||||
|
try:
|
||||||
|
self.sgrnumber = int(tem[30:33])
|
||||||
|
except:
|
||||||
|
self.sgrnumber = None
|
||||||
|
try:
|
||||||
|
self.sgrlabel = tem[34:38]
|
||||||
|
except:
|
||||||
|
self.sgrlabel = None
|
||||||
|
|
||||||
|
print self.latticetype, self.ineqvsite, self.sgrnumber, self.sgrlabel
|
||||||
|
infile.readline()
|
||||||
|
|
||||||
|
tem = infile.readline() # lattice constants
|
||||||
|
self.latticeconstants = [float(tem[0:10]), float(tem[10:20]), float(tem[20:30])]
|
||||||
|
self.latticeangle = [float(tem[30:40]), float(tem[40:50]), float(tem[50:60])]
|
||||||
|
print "Cell"
|
||||||
|
print self.latticeconstants[:]
|
||||||
|
print self.latticeangle[:]
|
||||||
|
|
||||||
|
self.positions = []
|
||||||
|
self.atomsymbols = []
|
||||||
|
self.multi = []
|
||||||
|
self.atomnumbers = []
|
||||||
|
self.locrotmatrix = []
|
||||||
|
for isite in range(self.ineqvsite):
|
||||||
|
tem = infile.readline()
|
||||||
|
positions = []
|
||||||
|
positions.append([float(tem[12:22]), float(tem[25:35]), float(tem[38:48])])
|
||||||
|
|
||||||
|
tem = infile.readline()
|
||||||
|
multi = int(tem[15:17])
|
||||||
|
self.multi.append(multi)
|
||||||
|
|
||||||
|
for im in range(multi - 1):
|
||||||
|
tem = infile.readline()
|
||||||
|
positions.append([float(tem[12:22]), float(tem[25:35]), float(tem[38:48])])
|
||||||
|
#print positions
|
||||||
|
self.positions.append(positions)
|
||||||
|
#print self.positions
|
||||||
|
tem = infile.readline().strip(" ").split()
|
||||||
|
self.atomsymbols.append(tem[0])
|
||||||
|
self.atomnumbers.append(float(tem[-1]))
|
||||||
|
|
||||||
|
mat = numpy.zeros((3, 3), dtype=numpy.float_)
|
||||||
|
tem = infile.readline().strip(" ").split()
|
||||||
|
#print tem[-3:],mat[0,:]
|
||||||
|
mat[0, :] = tem[-3:]
|
||||||
|
tem = infile.readline().strip(" ").split()
|
||||||
|
mat[1, :] = tem[-3:]
|
||||||
|
tem = infile.readline().strip(" ").split()
|
||||||
|
mat[2, :] = tem[-3:]
|
||||||
|
self.locrotmatrix.append(mat)
|
||||||
|
|
||||||
|
for ia in range(len(self.atomsymbols)):
|
||||||
|
print "atom symbol : %s atom number: %d atom multi: %d" % (self.atomsymbols[ia], self.atomnumbers[ia], self.multi[ia])
|
||||||
|
print "positions:"
|
||||||
|
for im in self.positions[ia]:
|
||||||
|
print im[:]
|
||||||
|
|
||||||
|
|
||||||
|
# symmetry with lattice vector
|
||||||
|
tem = infile.readline().strip(" ").split()
|
||||||
|
self.symm = []
|
||||||
|
self.tau = []
|
||||||
|
self.Nsymm = int(tem[0])
|
||||||
|
for isymm in range(self.Nsymm):
|
||||||
|
symmt = numpy.zeros((3, 3), dtype=float)
|
||||||
|
taut = numpy.zeros((3), dtype=float)
|
||||||
|
for ir in range(3):
|
||||||
|
s = infile.readline()
|
||||||
|
for ic in range(3):
|
||||||
|
symmt[ir][ic] = float(s[ic * 2:ic * 2 + 2])
|
||||||
|
taut[ir] = float(s[7:17])
|
||||||
|
self.symm.append(symmt)
|
||||||
|
self.tau.append(taut)
|
||||||
|
infile.readline()
|
||||||
|
|
||||||
|
#############
|
||||||
|
print "Read in %s.struct done!" % wiencase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## convential Cell Volume and primitive Cell. In bohr^3 unit
|
||||||
|
self.VolumeCC, self.VolumePC = cellvolume(self.latticetype, self.latticeconstants, self.latticeangle)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def readSGsymm(self, wiencase):
|
||||||
|
""" read in symmetry of space group from wiencase.outputs other than wiencase.struct since
|
||||||
|
in this file there are also symmetry operations in xyz coordinates..
|
||||||
|
"""
|
||||||
|
structfile = wiencase + ".outputs"
|
||||||
|
self.nsymm = 1
|
||||||
|
self.symm = []
|
||||||
|
self.tau = []
|
||||||
|
# note bravaismatrix is not accurate enough in wiencase.outputs file. Just use it for test.
|
||||||
|
self.bravaismatrix = numpy.zeros((3, 3), dtype=numpy.float_)
|
||||||
|
self.symmcartesian = []
|
||||||
|
self.taucartesian = []
|
||||||
|
with open(structfile, "r") as f:
|
||||||
|
f.readline()
|
||||||
|
f.readline()# bravais matrix
|
||||||
|
for i in range(3):
|
||||||
|
line = f.readline().strip().split()
|
||||||
|
self.bravaismatrix[i, :] = numpy.array([numpy.float(item) for item in line])[:]
|
||||||
|
print "bravais matrix", self.bravaismatrix
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
try:
|
||||||
|
s = f.readline().strip(" ").split()
|
||||||
|
if(s[0] == "PGBSYM:"):
|
||||||
|
self.nsymm = int(s[-1])
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
assert "Error in read case.outputs"
|
||||||
|
|
||||||
|
#f.readline()
|
||||||
|
#f.readline()
|
||||||
|
for i in range(self.nsymm):
|
||||||
|
while 1:
|
||||||
|
s = f.readline().strip().split()
|
||||||
|
if s[0] == "Symmetry":
|
||||||
|
break
|
||||||
|
|
||||||
|
## read symmcartesian
|
||||||
|
symmt = numpy.zeros((3, 3), dtype=float)
|
||||||
|
taut = numpy.zeros((3), dtype=float)
|
||||||
|
for ir in range(3):
|
||||||
|
s = f.readline().strip().split()
|
||||||
|
for ic in range(3):
|
||||||
|
symmt[ir, ic] = float(s[ic])
|
||||||
|
s = f.readline().strip().split()
|
||||||
|
for ir in range(3):
|
||||||
|
taut[ir] = float(s[ir])
|
||||||
|
|
||||||
|
self.symmcartesian.append(symmt)
|
||||||
|
self.taucartesian.append(taut)
|
||||||
|
|
||||||
|
##read symm
|
||||||
|
symmt = numpy.zeros((3, 3), dtype=float)
|
||||||
|
taut = numpy.zeros((3), dtype=float)
|
||||||
|
for ir in range(3):
|
||||||
|
s = f.readline().strip().split()
|
||||||
|
for ic in range(3):
|
||||||
|
symmt[ir, ic] = numpy.float(s[ic])
|
||||||
|
taut[ir] = numpy.float(s[3])
|
||||||
|
|
||||||
|
self.symm.append(symmt)
|
||||||
|
self.tau.append(taut)
|
||||||
|
|
||||||
|
# end
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
def checksymmxyz(self):
|
||||||
|
''' This is to check symm in cartesian coordinates and in primitive cell lattice
|
||||||
|
For details of symm, should check wien/SRC_symmetry/, latsym.f, pglsym.f,pgbsym.f
|
||||||
|
In general, if a lattice is orthorhombic, then symmcartesian is the same as symmprimitive
|
||||||
|
(at most different by a transpose (or inversion)). If a lattice is not orthorhombic, these two symms could
|
||||||
|
be related by bravais matrix.
|
||||||
|
One special case is CXZ lattice. In Wien CXZ lattice contains two cases: orthorhombic, and
|
||||||
|
monoclinic (with only gamma not equal to 90). For CXZ lattice monoclinic, symmcartesian is also the same as
|
||||||
|
symmprimitive (or with transpose (or inversion)).
|
||||||
|
'''
|
||||||
|
ortho = numpy.abs(numpy.array(self.latticeangle) - 90.0).sum() <= 1e-6
|
||||||
|
for i in range(self.nsymm):
|
||||||
|
mat = self.symmcartesian[i].transpose() # according to wien2k, why?
|
||||||
|
res = mat
|
||||||
|
if (not ortho) and (self.latticetype != "CXZ") :
|
||||||
|
bm = self.bravaismatrix
|
||||||
|
bminv = numpy.linalg.inv(bm)#.transpose()
|
||||||
|
res = numpy.dot(bminv, numpy.dot(mat, bm))
|
||||||
|
res -= self.symm[i]
|
||||||
|
print i, numpy.abs(res).sum()
|
||||||
|
|
||||||
|
## primitive cell vectors.+
|
||||||
|
|
Loading…
Reference in New Issue
Block a user