怎么画EPW计算里面3维的gap

以下内容全部参考EPW: Superconducting gap on the Fermi surface (需要梯子)
首先需要算出费米面,官方提供了两个脚本,一个是用来画出三维的费米面,一个是后处理费米面上每个点对应的gap。原版是python2的,可以在这里找到Fermi,我平时用python3,所以就转换了一下贴在下面
fermi_surf.py

#
# Script developed by H. Lambert and S. Ponce [2016]
#
import sys
import re
import numpy as np

def parse_args(args):
  extra = []
  vars  = []
  current_var = None
  for arg in args:
    if arg.startswith('--'):
      current_var = arg[2:]
    else:
      if current_var is not None:
        vars.append((current_var, arg))
        current_var = None
      else:
        extra.append(arg)
  return (extra, vars)

def split_vars(vars):
  vars_values = []
  for var_name, values in vars:
    values = values.split(",")
    try:
      if any(['.' in value for value in values]):
        values = list(map(float, values))
      else:
        values = list(map(int, values))
    except ValueError:
      pass
    vars_values.append((var_name, values))
  vars_dict = dict(vars_values)
  return vars_dict

#f is a string with the contents of the file
class FermiSurface(object):
  def __init__(self):
    self.nx = 60
    self.ny = 60
    self.nz = 60
    self.dimvec = np.array([float(self.nx), float(self.ny), float(self.nz)])
    self.fermixyz = {}
    self.gap = {}
    self.prefix = 'MgB2'
    self.nbndmin = 2
    self.nbndmax = 4

  def __repr__(self):
    return 'Fermi Surface/Mu Tensor Object'

  def cryst_to_cart(self, kvec):
#MgB2 crystal axes
    at1 = np.array([ 1.000000,   0.000000,   0.000000])
    at2 = np.array([-0.500000,   0.866025,   0.000000])
    at3 = np.array([ 0.000000,   0.000000,   1.142069])
    at  = np.array([at1, at2, at3])
    outvec = np.dot(at, kvec)
    return outvec

  def pull_fermi(self,f):
    fermi_regex  = re.compile(r'k\s=\s?(\-?[0-9\.]+)\s?(\-?[0-9\.]+)\s?(\-?[0-9\.]+).*?:\n\n\s+([0-9\.\-\s]+)')
    print(len(fermi_regex.findall(f)))
    for a, b, c, d in fermi_regex.findall(f):
      a = float(a)
      b = float(b)
      c = float(c)
      kvec = np.array([a,b,c])
      d = list(map(float, d.split()))
      kvec = self.cryst_to_cart(kvec)
  
      #Fold into first brillouin zone:
      for i, a in enumerate(kvec):
        if (a< -0.001): kvec[i] = kvec[i] + 1.0
      index = [round(a) for a in np.multiply(kvec, self.dimvec)]

      # Rescale the energy so that the Fermi level = 0
      d[:] = [x - 7.4272 for x in d]

      for i, a in enumerate(index):
        if index[i] == 61.0: 
          index[i] = 0.0
      print(index)
      self.fermixyz[tuple(index)] = d

#returns dictionary keys:xyz coordinates, values:eigenvalues.
  def print_xsf(self, surf, title='band', band1=2, band2=3, band3=4):
    for ibnd in range(band1, band3+1):
      f1 = open('{0}.band{1}.xsf'.format(self.prefix, ibnd), 'w')
      print("BEGIN_BLOCK_DATAGRID_3D", file=f1) 
      print("{0}_band_{1}".format(self.prefix, ibnd), file=f1)     
      print(" BEGIN_DATAGRID_3D_{0}".format(self.prefix), file=f1) 
      print(" {0}  {1}  {2} ".format(self.nx, self.ny, self.nz), file=f1)
      print("0.000000  0.000000  0.000000", file=f1)   
    #MgB2:
      print("1.000000  0.577350  0.000000", file=f1)
      print("0.000000  1.154701  0.000000", file=f1)
      print("0.000000  0.000000  0.875604", file=f1)
      print("", file=f1)
      
      total = 0
      for z in range(self.nz):
        for y in range(self.ny):
          for x in range(self.nx):
            try:
              print(surf[x,y,z][ibnd], " ", end=' ', file=f1)
              #print>>f1, "0.05", " ",
              total = total+ 1 
            except TypeError:
              print(surf[x,y,z], " ", end=' ', file=f1)
              print('Missing key')
              print("0.0", " ", end=' ', file=f1)
            except KeyError:
              print('Missing key') 
              print("0.0", " ", end=' ', file=f1)
          print("", file=f1)
        print("", file=f1)
      print("END_DATAGRID_3D", file=f1)  
      print("END_BLOCK_DATAGRID_3D", file=f1)  
      f1.close()
      print('Total number of data ',total)


if __name__=="__main__":
# run as: 
# python --fs y ./nscf.out to parse band file and make fermiplot
# else run as:
# python --gap y name to parse gap plot.
  extra, vars = parse_args(sys.argv[1:])
  vars_values = []

  vars = split_vars(vars)
  print(vars, extra)

  f = open(extra[0]).read()
  fs = FermiSurface()

  if 'fs' in list(vars.keys()):
    fs.pull_fermi(f)
    fs.print_xsf(fs.fermixyz, band1=2, band2=3, band3=4)


fermi_gap.py

#
# Script developed by H. Lambert and S. Ponce [2016]
#
import sys
import re
import numpy as np

def parse_args(args):
  extra = []
  vars  = []
  current_var = None
  for arg in args:
    if arg.startswith('--'):
      current_var = arg[2:]
    else:
      if current_var is not None:
        vars.append((current_var, arg))
        current_var = None
      else:
        extra.append(arg)
  return (extra, vars)

def split_vars(vars):
  vars_values = []
  for var_name, values in vars:
    values = values.split(",")
    try:
      if any(['.' in value for value in values]):
        values = list(map(float, values))
      else:
        values = list(map(int, values))
    except ValueError:
      pass
    vars_values.append((var_name, values))
  vars_dict = dict(vars_values)
  return vars_dict

#f is a string with the contents of the file
class FermiSurface(object):
  def __init__(self):
    self.nx = 60
    self.ny = 60
    self.nz = 60
    self.dimvec = np.array([float(self.nx), float(self.ny), float(self.nz)])
    self.fermixyz = {}
    self.gap = {}
    self.prefix = 'MgB2'
    self.nbndmin = 2
    self.nbndmax = 4

  def __repr__(self):
    return 'Fermi Surface/Mu Tensor Object'

  def cryst_to_cart(self, kvec):
#MgB2 crystal axes
    at1 = np.array([ 1.000000,   0.000000,   0.000000])
    at2 = np.array([-0.500000,   0.866025,   0.000000])
    at3 = np.array([ 0.000000,   0.000000,   1.142069])
    at  = np.array([at1, at2, at3])
    outvec = np.dot( kvec,at)
    return outvec

  def cart_to_cryst(self, kvec):
#crystal to cart BG MgB2
    at1 = np.array([ 1.000000,  -0.500000,   0.000000])
    at2 = np.array([ 0.000000,   0.866025,   0.000000])
    at3 = np.array([ 0.000000,   0.000000,   1.142069])
    at  = np.array([at1, at2, at3])
    outvec = np.dot(kvec,at)
    return outvec

  def pull_fermi(self,f):
    fermi_regex  = re.compile(r'k\s=\s?(\-?[0-9\.]+)\s?(\-?[0-9\.]+)\s?(\-?[0-9\.]+).*?:\n\n\s+([0-9\.\-\s]+)')
    print(len(fermi_regex.findall(f)))
    for a, b, c, d in fermi_regex.findall(f):
      a = float(a)
      b = float(b)
      c = float(c)
      kvec = np.array([a,b,c])
      d = list(map(float, d.split()))
      kvec = self.cryst_to_cart(kvec)
  
      #Fold into first brillouin zone:
      for i, a in enumerate(kvec):
        if (a< -0.001): kvec[i] = kvec[i] + 1.0
      index = [round(a) for a in np.multiply(kvec, self.dimvec)]

      # Rescale the energy so that the Fermi level = 0
      d[:] = [x - 7.4272 for x in d]

      for i, a in enumerate(index):
        if index[i] == 61.0: 
          index[i] = 0.0
      print(index)
      self.fermixyz[tuple(index)] = d

  def pull_fermi_xy(self,f):
    fermi_regex  = re.compile(r'k\s=\s?(\-?[0-9\.]+)\s?(\-?[0-9\.]+)\s?(\-?[0-9\.]+).*?:\n\n\s+([0-9\.\-\s]+)')
    print(len(fermi_regex.findall(f)))
    for a, b, c, d in fermi_regex.findall(f):
      a    = float(a)
      b    = float(b)
      c    = float(c)
      kvec = np.array([a,b,c])
      d    = list(map(float, d.split()))
      # Turn kpoint coordinates into integer indices
      # and fold back into the first Brillouin zone.
      kvec = self.cryst_to_cart(kvec)
      # Fold into first Brillouin zone:
      for i, a in enumerate(kvec):
        if (a<0.0): kvec[i] = kvec[i] + 1.0
      index = [round(a) for a in np.multiply(kvec, self.dimvec)]
      for i, a in enumerate(index):
        if index[i] == 61.0:
          index[i] = 0.0     

#returns dictionary keys:xyz coordinates, values:eigenvalues.
  def print_xsf(self, surf, title='band', band1=1):
    for ibnd in range(band1):
      f1 = open('{0}.col.band{1}.xsf'.format(self.prefix, ibnd), 'w')
      print("BEGIN_BLOCK_DATAGRID_3D", file=f1) 
      print("{0}_band_{1}".format(self.prefix, ibnd), file=f1)     
      print(" BEGIN_DATAGRID_3D_{0}".format(self.prefix), file=f1) 
      print(" {0}  {1}  {2} ".format(self.nx, self.ny, self.nz), file=f1)
      print("0.000000  0.000000  0.000000", file=f1)   
    #MgB2:
      print("1.000000  0.577350  0.000000", file=f1)
      print("0.000000  1.154701  0.000000", file=f1)
      print("0.000000  0.000000  0.875604", file=f1)
      print("", file=f1)
      
      total = 0
      for z in range(self.nz):
        for y in range(self.ny):
          for x in range(self.nx):
            try:
              print(surf[x,y,z], " ", end=' ', file=f1)
              #print>>f1, "0.05", " ",
              total = total+ 1 
            except TypeError:
              print(surf[x,y,z], " ", end=' ', file=f1)
              print('Missing key')
              print("0.0", " ", end=' ', file=f1)
            except KeyError:
              print('Missing key') 
              print("0.0", " ", end=' ', file=f1)
          print("", file=f1)
        print("", file=f1)
      print("END_DATAGRID_3D", file=f1)  
      print("END_BLOCK_DATAGRID_3D", file=f1)  
      f1.close()
      print('Total number of data ',total)

  def pull_muk(self, f):
    total = 0
    for line in f.split('\n'):
      try:
        a,b,c,d,e,f = list(map(float, line.split()))
        # Do one band d manually
        if d == 2:
          kvec = np.array([a,b,c])
          kvec = self.cart_to_cryst(kvec)

          index = [round(ii) for ii in np.multiply(kvec, self.dimvec)]
          print(index)
          self.gap[tuple(index)] = f
          total += 1
      except:
        print("Couldn't read the following line:")
        print(line)
    print('Total number of lines extracted ',total)  

if __name__=="__main__":
# run as: 
# python --fs y ./nscf.out to parse band file and make fermiplot
# else run as:
# python --gap y name to parse gap plot.
  extra, vars = parse_args(sys.argv[1:])
  vars_values = []

  vars = split_vars(vars)
  print(vars, extra)

  f = open(extra[0]).read()
  fs = FermiSurface()

  if 'fs' in list(vars.keys()):
    fs.pull_fermi(f)
    fs.print_xsf(fs.fermixyz, band1=2, band2=3, band3=4)

  if 'gap' in list(vars.keys()):
    fs.pull_muk(f)
    fs.print_xsf(fs.gap, 'gap')


然后第一步是算出费米面,通过nscf计算得到

srun --mpi=pmi2 $EXE/pw.x  <nscf.in> nscf.out

nscf输入文件如下,有两个点需要注意,首先nosym,noinv需要打开,要不然画出来费米面是约化之后的,只有一部分费米面。第二点是需要设置QE的Modules/parameters.f90中改一下npk,改的大一些,比你要算费米面用到的k点个数大,否则会报错,改完之后重新编译pw,nscf.in的输入文件我贴在这里

 &control
    calculation='nscf',
    prefix='MgB2',
    pseudo_dir = '../../pp/',
    outdir='./',
    tprnfor = .true.,
    tstress = .true.,
    etot_conv_thr = 1.0d-5
    forc_conv_thr = 1.0d-4
    verbosity = 'high'
    disk_io = 'none'
 /
 &system
    ibrav = 4,
    celldm(1) = 5.8260252227888,
    celldm(3) = 1.1420694129095,
    nat=  3,
    ntyp = 2,
    ecutwfc = 40
    smearing = 'mp'
    occupations = 'smearing'
    degauss = 0.02
    nosym = .t.
    noinv = .t.
 /
 &electrons
    diagonalization = 'david'
    mixing_mode = 'plain'
    mixing_beta = 0.7
    conv_thr =  1.0d-9
 /
ATOMIC_SPECIES
 Mg  24.305  Mg.pz-n-vbc.UPF
 B   10.811  B.pz-vbc.UPF
ATOMIC_POSITIONS crystal
Mg       0.000000000   0.000000000   0.000000000
B        0.333333333   0.666666667   0.500000000
B        0.666666667   0.333333333   0.500000000
K_POINTS AUTOMATIC
60 60 60 0 0 0

这时会输出一个很大的nscf.out文件,然后用python脚本处理

python fermi_surf.py --fs -y nsfcf.out

会产生几个费米面的文件
MgB2.band2.xsf,MgB2.band3.xsf,MgB2.band4.xsf
然后用VESTA画出来就行了。
直接把MgB2.band2.xsf拖进VESTA,另外两个import进去,Eidt-Edit data-volumetric data在上面的isosurface import进去就得到费米面了。Operation选Multiply to current data,其余默认
再做两个调整
1、Properties-Isosurface里面isosurface level改成0,
2、Properties-SectionsOpacity of isosurfaces' sections改成0

MgB2.band.png

然后第二步,后处理超导能隙。信息是从EPW计算的MgB2.imag_aniso_gap_FS_XX.00文件中提取,XX对应你计算的时候选定的温度,注意自己修改。
命令是

python fermi_gap.py --gap -y MgB2.imag_aniso_gap_FS_XX.00

然后会生成MgB2.col.band0.xsf文件,就是对应的gap的信息,先随便改成另一个文件名,然后更改fermi_gap.py中的第160行,if d == 2:改成if d == 1:,再执行一遍,生成另一个费米面上的gap(MgB2是双带超导,所以这里有两个)生成两条带上的gap以后,同样的方法导入到VESTA中,Eidt-Edit data-volumetric data,这一次是导入到下面那个Surface Coloring中。Operation直接选默认。然后就得到费米面上的gap图了。

MgB2.band_gap.png

这里做个演示计算量限制,选取的k点网格是20x20x20,所以跟官网上不太一样,用60x60x60计算得到的gap就能和官网上类似了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容