我现在想用VASP计算的RuO2,并实现输出wannier90的输入文件。我目前的INCAR如下: ...
Creado el: 24 de febrero de 2026
Respondido usando GPT-5.2 Thinking por Chat01
Creado el: 24 de febrero de 2026
Respondido usando GPT-5.2 Thinking por Chat01
我现在想用VASP计算的RuO2,并实现输出wannier90的输入文件。我目前的INCAR如下:
SYSTEM = RuO2
NPAR = 8
KPAR = 8
ISTART = 0
ICHARG = 2
ISMEAR = 1
SIGMA = 0.15
ENCUT = 520
EDIFF = 1E-8
GGA = PE
LORBIT = 11
PREC = A
AMIX = 0.2
BMIX = 0.01
AMIX_MAG = 0.8
BMIX_MAG = 0.04
NEDOS = 2400
NELMIN = 6
NELM = 100
LMAXMIX = 4
LREAL = .FALSE
LWAVE = .FALSE
LCHARG = .TRUE
ADDGRID = .TRUE
GGA_COMPAT = .FALSE.
NSW = 0
IBRION = -1
POTIM = 0.2
ISIF = 2
EDIFFG = -0.001
NBANDS = 64
ISPIN = 2
MAGMOM = 2 -2 4*0
LWANNIER90 = .TRUE.
POSCAR如下:
RuO2
1.00000000000000
4.6515700000000004 0.0000000000000000 0.0000000000000000
0.0000000000000000 4.6515700000000004 0.0000000000000000
0.0000000000000000 0.0000000000000000 2.9695930000000001
Ru O
2 4
Direct
0.5000000000000000 0.5000000000000000 0.5000000000000000
-0.0000000000000000 0.0000000000000000 0.0000000000000000
0.2014855089968415 0.7985144910031586 0.5000000000000000
0.7985144910031586 0.2014855089968415 0.5000000000000000
0.7014855089968414 0.7014855089968414 0.0000000000000000
0.2985144910031585 0.2985144910031585 -0.0000000000000000
0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00
我该怎么修改我的INCAR?(我希望Ru投影d轨道,O投影p轨道)
你现在的 INCAR 里已经有 LWANNIER90 = .TRUE.,但要稳定地让 VASP 把 Wannier90 所需输入文件(wannier90.win/mmn/amn/eig 等)写出来,以及实现你要的 Ru:d、O:p 投影,建议按下面做(尤其是金属体系 RuO):
wannier90.win(或 WANNIER90_WIN)里写VASP 在 LWANNIER90=.TRUE. 时会写出 wannier90.win, wannier90.mmn, wannier90.amn, wannier90.eig 等文件;并且如果你在 wannier90.win 里提供 projections 块,VASP 会按这个投影去生成 amn(投影矩阵)。 (vasp.at)
Wannier90 的投影语法本身支持 s/p/d/f 等角动量投影。 (wannier90.readthedocs.io)
唯一强烈建议:把波函数写出来,给第二步复用
iniLWAVE = .TRUE. LCHARG = .TRUE.
(你现在 LWAVE=.FALSE.,第二步就没法 ISTART=1 复用 WAVECAR 了。)
另外你这行建议修正一下小拼写:
LREAL = .FALSE→LREAL = .FALSE.(少了最后那个点在一些版本会出问题)
把第一步生成的 WAVECAR、CHGCAR 复制/保留到当前目录,然后用下面这套 INCAR 跑一次:
ini# --- restart / nscf --- ISTART = 1 ICHARG = 11 NELM = 1 # --- wannier interface --- LWANNIER90 = .TRUE. LWRITE_MMN_AMN = .TRUE. # 如果你还想输出 UNK 用来画 Wannier 函数(可选) # LWRITE_UNK = .TRUE. # --- symmetry (important for k-mesh based wannier) --- ISYM = 0 # --- band / wannier number --- NBANDS = 64 NUM_WANN = 22
说明:
LWANNIER90 会让 VASP 写出 wannier90 所需文件。 (vasp.at)wannier_run,而是想拿到 mmn/amn 在外部单独跑 wannier90,显式加上 LWRITE_MMN_AMN=.TRUE. 最稳妥。 (vasp.at)NUM_WANN=22 对应你要的投影数量:
NUM_WANN 也会用于 wannier90,并写进 wannier90.win 里的 num_wann。 (vasp.at)ISYM=0 一般用于避免对 k 点做对称性约化,减少 Wannier 接口里邻接关系/权重相关的坑(尤其新手阶段很推荐)。小提示:如果你使用
KPAR>1有时会遇到 wannier 文件不全/接口异常(取决于 VASP 版本和编译选项),排查时先把KPAR=1试一下最省事。
wannier90.win 模板(你要的 Ru:d + O:p)在第二步跑之前,在目录里放一个 wannier90.win(这样 VASP 就会按你的投影生成 amn): (vasp.at)
textnum_wann = 22 begin projections Ru:d O:p end projections
Wannier90 投影语法本身支持这种按元素+角动量的写法(p/d 等)。 (wannier90.readthedocs.io)
WANNIER90_WIN(VASP≥6.2.0)如果你是 VASP 6.2.0 或更新版本,可以直接在 INCAR 写多行字符串,让 VASP 生成/补全 wannier90.win: (vasp.at)
iniWANNIER90_WIN = " begin projections Ru:d O:p end projections "
如果你告诉我你用的 VASP 版本号、以及 KPOINTS 的网格(比如 8×8×12 之类),我可以顺手帮你把 wannier90.win 里 disentanglement(dis_win_* / dis_froz_*)窗口也按 RuO 金属体系的常见做法配得更稳。
Wannier90 mode
Computing MMN (overlap matrix elements)
Abort(1) on node 47 (rank 47 in comm 0): application called MPI_Abort(MPI_COMM_WORLD, 1) - process 47
Wannier90 mode
Computing MMN (overlap matrix elements)
Abort(1) on node 47 (rank 47 in comm 0): application called MPI_Abort(MPI_COMM_WORLD, 1) - process 47
我不理解为什么它会默认num_wannier=34
这个 34 并不是“凭空默认出来的”,它几乎肯定来自 NBANDS。
在 VASP 的 wannier90 接口里有两件事会把“wannier 个数”绑到 NBANDS 上:
wannier90.win,VASP 会自动生成一个模板,并把里面的num_wann = NBANDS 写进去。 (VASP)所以你现在看到 “NUM_WANN is 34”,最常见原因就是:你这一次 wannier 这步实际用的 NBANDS=34(可能是你改过,或该步没写 NBANDS 让 VASP 自动给了 34),于是 NUM_WANN 也跟着变成 34。
而你 projections(Ru:d + O:p)只有 22 个投影,所以 VASP 才提示:
returning 22 projections while NUM_WANN is 34
用于 wannier 的那一步(通常是 NSCF,ICHARG=11)建议至少包含:
iniISTART = 1 ICHARG = 11 NELM = 1 LWANNIER90 = .TRUE. LWRITE_MMN_AMN = .TRUE. NUM_WANN = 22 NBANDS = 64 # 只要 >= 22 且满足你的能窗/纠缠需求即可 ISYM = -1 KPAR = 1
NUM_WANN=22:和你的投影数一致ISYM=-1:完全关闭对称性/时间反演约化,避免 k 点不全导致 mmn 邻接出问题 (VASP)KPAR=1 排除并行导致的接口崩溃(你现在就是在 “Computing MMN” 时 MPI_Abort)。wannier90.win 也保持一致(推荐)用最小骨架文件就行(让 VASP 自动补 kpoints/mp_grid):
textnum_wann = 22 num_bands = 64 begin projections Ru:d O:p end projections
重点:不要在 win 里手动放
kpointsblock(或者把它删掉)。VASP 明确说过:如果它发现 win 里已经有 kpoints block,它不会检查是否和你这次 VASP 的 KPOINTS 一致。 (VASP)
kpoints 不一致是导致 mmn 生成阶段直接崩的高频原因之一。
那条只是说:你在 win 里手动设了 zona,而 VASP 5.4.4~6.3 之间对单位的历史假设有坑,用于提醒“和老版本结果对比时要换单位”;本身不等于出错。
KPAR=1 + 删 win 里 kpoints block 最快定位)如果你把你 wannier 那一步的 INCAR(尤其 NBANDS/NUM_WANN/ISYM/KPAR)和你当前目录的 wannier90.win 前 50 行贴出来,我可以直接指出到底是哪一条把它变成了 34,以及导致 MMN 崩溃的最具体原因。
我现在想用wannier90做一个Berry曲率的空间分布图,但我发现我似乎无法输出各个位置的berry曲率,你有什么办法吗?
你碰到的“无法输出各个位置的 Berry 曲率”,多数情况下是把“空间分布”理解成实空间 r 了;但 Wannier90 / postw90 默认能直接给的是 k 空间(布里渊区里每个 k 点)的 Berry 曲率分布。下面给你两条路:** (A) k 空间分布图(Wannier90 原生支持)、(B) 实空间“局域分布”(Wannier90 不原生输出,需要换定义/换工具)**。
postw90 的 kslice 或 kpathkslice_task = curv在 seedname.win(例如 RuO2.win)里加这些(关键字在 postw90 参数表里就有:kslice_corner/b1/b2/kslice_2dkmesh 等) (Wannier90)
textfermi_energy = <填你的费米能> # 金属必须给;单位 eV(通常) berry_curv_unit = bohr2 # 可选:输出单位 kslice = true kslice_task = curv # 只画 Berry 曲率热图 # kslice_task = curv+fermi_lines # 也可以叠加费米线(如果你想看“热点”在费米面附近) # 用“约化坐标”(reduced coordinates)定义一个 BZ 平面: kslice_corner = 0.0 0.0 0.0 kslice_b1 = 1.0 0.0 0.0 kslice_b2 = 0.0 1.0 0.0 # 平面网格密度(越大越细) kslice_2dkmesh = 301 301
这会生成“在你指定平面上的每个 k 点”的 Berry 曲率数据。
bashpostw90.x RuO2
postw90 的 kslice 会明确写出这些文件名: (wannier.org)
RuO2-kslice-coord.dat:每个网格点的 (k_x, k_y) 坐标(用于画图定位)RuO2-kslice-curv.dat:每个网格点的 Berry 曲率(按分量写出;脚本会用列号读取)RuO2-kslice-curv_x.py / _y.py / _z.py 或带 +fermi_lines 的版本 (wannier.org)小细节:
kslice模块里写的是“输出 minus the Berry curvature(负号)并对占据态求和”,所以你看到的热图可能是 -Ω(k)(这不是你错了,是它的定义/输出约定)。(wannier.org)
kpath_task = bands+curv如果你要的是沿高对称线的 Ω(k),用 kpath 更合适。Wannier90 教程 18 就是这么做的: (Wannier90)
textfermi_energy = <填你的费米能> kpath = true kpath_task = bands+curv kpath_num_points = 1000
严格地讲,Berry 曲率是定义在 k 空间的几何量(Ω_n(k))。Wannier90/postw90 的 “berry / kslice / kpath”模块也是在 k-space 工作的 (Wannier90)。
如果你想画“实空间中哪里贡献大”的那种图,一般需要换成局域拓扑标记的定义,例如 Bianco–Resta local Chern marker(局域陈数标记),它能在实空间格点/原子附近给出“局域拓扑贡献”。PythTB 就有现成教程示例可以直接把 marker 画成 real-space map: (pythtb.readthedocs.io)
典型工作流是:
wannier90_hr.dat(Wannier 哈密顿量)构建紧束缚模型/超胞(可开边界)wannier90.x RuO2 得到 RuO2.chk?postw90 需要它。kslice,你一定会得到 RuO2-kslice-curv.dat + RuO2-kslice-coord.dat (wannier.org)如果你把你现在的 RuO2.win 里和 postw90 相关的部分(以及你想看的平面:比如 kz=0 或 ky=0)贴出来,我可以直接帮你把 kslice_corner/b1/b2 按你的晶格方向写成“对的那张切片”。
那我怎么得到不同kslice的mapping呢?我现在的win文件如下,这个程序可以跑通:
dis_num_iter = 100
num_iter = 100
dis_win_min = -22
dis_win_max = 15
dis_froz_min = -9
dis_froz_max = 5.5
begin projections
O:p
Ru:d
end projections
fermi_energy = 6.700615
berry_curv_unit = bohr2
berry = true
berry_task = curv
kpath = true
kpath_num_points = 1000
num_bands = 64
num_wann = 22
剩下的部分都是原子位置以及k点位置
你现在这个 .win 跑通的是 kpath 上的 Berry 曲率(kpath=true),所以只能得到“沿路径”的数据;如果你要的是 某个 BZ 平面上的 2D mapping(热力图),要用 kslice 模块(kslice=true)。
下面把“怎么得到不同 kslice 的 mapping”讲清楚:怎么定义切片、怎么批量扫不同切片、以及怎么把每个网格点对应回 3D k 点。
kslice_task=curv 会输出 2D 平面上每个网格点的 Berry 曲率,并生成画图脚本与数据文件:seedname-kslice-coord.dat + seedname-kslice-curv.dat (Wannier90)
建议你在现有内容基础上加:
textkslice = true kslice_task = curv # 或 curv+fermi_lines(叠加费米线更直观) kslice_2dkmesh = 201 201 # 网格 (N1+1)x(N2+1),越大越细 # 下面三行决定“切哪个平面”(reduced coordinates) kslice_corner = 0.0 0.0 0.0 kslice_b1 = 1.0 0.0 0.0 kslice_b2 = 0.0 1.0 0.0
注意:kslice_corner / b1 / b2 是约化坐标(reduced coordinates),也就是用倒格矢基矢表示的系数;文档里就是这么定义的 (Wannier90)
你现有的
berry=true / berry_task=curv其实不必保留(berry_task的合法项主要是 kubo/kdotp 等),做 kslice 时通常可以把berry=false,只保留kpath和/或kslice,更干净 (Wannier90)
对你这个四方/金红石结构(晶轴和坐标轴对齐),最常用的是固定 kz = 常数 的切片:
kz = 0 平面:
textkslice_corner = 0.0 0.0 0.0 kslice_b1 = 1.0 0.0 0.0 kslice_b2 = 0.0 1.0 0.0
kz = 0.25 平面:
textkslice_corner = 0.0 0.0 0.25 kslice_b1 = 1.0 0.0 0.0 kslice_b2 = 0.0 1.0 0.0
kz = 0.5 平面:
textkslice_corner = 0.0 0.0 0.5 ...
同理,如果你要 ky=0 平面(kx–kz):
textkslice_corner = 0.0 0.0 0.0 kslice_b1 = 1.0 0.0 0.0 kslice_b2 = 0.0 0.0 1.0
b1/b2 只要线性无关就行,否则会报错 (wannier.org)
Wannier90 的 kslice 网格是按整数索引 扫描的,系数是
kslice_2dkmesh)这就是源码里直接写的:kpt = kslice_corner + k1*kslice_b1 + k2*kslice_b2 (wannier.org)
而输出文件中:
seedname-kslice-curv.dat:按同样顺序写出每个点的 (curv 时是三分量) (Wannier90)seedname-kslice-coord.dat:写的是切片平面上的 2D “笛卡尔坐标” (kpt_x,kpt_y),用于画图(不是 3D k) (wannier.org)所以如果你想要“每个点的 3D k + Berry 曲率”表格,最稳的方法是:用你自己按上面的公式把 3D k 算出来,再跟 curv.dat 拼起来。
下面给你一个直接可用的 Python(假设 kslice_2dkmesh = N1 N2):
pythonimport numpy as np N1, N2 = 201, 201 # 改成你的 kslice_2dkmesh corner = np.array([0.0, 0.0, 0.25]) # 改成你的 kslice_corner b1 = np.array([1.0, 0.0, 0.0]) # 改成你的 kslice_b1 b2 = np.array([0.0, 1.0, 0.0]) # 改成你的 kslice_b2 coord = np.loadtxt("RuO2-kslice-coord.dat") # (Nk,2) : kpt_x, kpt_y curv = np.loadtxt("RuO2-kslice-curv.dat") # (Nk,3) : Omega_x, Omega_y, Omega_z Nk = (N1+1)*(N2+1) assert coord.shape[0] >= Nk and curv.shape[0] >= Nk kred = np.zeros((Nk,3)) idx = 0 for i2 in range(N2+1): for i1 in range(N1+1): k1 = i1 / float(N1) k2 = i2 / float(N2) kred[idx,:] = corner + k1*b1 + k2*b2 idx += 1 out = np.hstack([kred, coord[:Nk,:], curv[:Nk,:]]) np.savetxt("RuO2_kslice_mapping.dat", out, header="kred1 kred2 kred3 kpt_x kpt_y Omega_x Omega_y Omega_z") print("Wrote RuO2_kslice_mapping.dat")
最简单:写个 bash 循环,每次改 kslice_corner,跑 postw90.x,然后把输出文件改名保存(避免覆盖)。
示例(扫 kz = 0.0, 0.05, …, 0.5):
bashfor kz in 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50; do sed "s/^kslice_corner.*/kslice_corner = 0.0 0.0 ${kz}/" RuO2.win > RuO2_tmp.win mv RuO2_tmp.win RuO2.win postw90.x RuO2 mkdir -p slices mv RuO2-kslice-*.dat RuO2-kslice-*.py slices/ # 你也可以在这里调用上面的 python 脚本生成 mapping.dat done
如果你告诉我你具体想扫的是:
我可以直接帮你把 kslice_corner/b1/b2 写成你要的那组平面定义(保证是 reduced coords、且画出来形状正常)。
它输出了5个文件,名字分别是:wannier90_up-kslice-coord.dat wannier90_up-kslice-curv.dat wannier90_up-kslice-curv_x.py wannier90_up-kslice-curv_y.py wannier90_up-kslice-curv_z.py
这分别代表什么意思?
这 5 个文件都是 postw90 的 kslice 模块在做“BZ 平面切片上的 Berry 曲率热图”时自动生成的;前缀 wannier90_up 说明你现在跑的是 自旋上(spin-up)通道对应的 seedname(通常自旋下会是 wannier90_dn,如果你也做了它的话)。
下面逐个解释它们是什么、里面是什么数据、怎么用:
wannier90_up-kslice-coord.dat这是 切片平面上每个网格点的 2D 坐标文件:两列数据 。
kslice_b1 方向)。源码里明确写了它就是 “Convert to (kpt_x,kpt_y), the 2D Cartesian coordinates”。(wannier.org)wannier90_up-kslice-curv.dat这是 切片平面上每个网格点的 Berry 曲率数值文件。
-kslice-coord.dat 里同一行的那个网格点。(wannier.org)kslice_task = curv,它写的是 三分量(通常可理解为 ),并且在代码里是把曲率 对占据能带求和之后再输出的。(wannier.org)my_zdata = -curv,注释也写 “Print minus the Berry curvature”)。所以你图上看到的是 的分布,这是程序约定,不是你算错。(wannier.org)berry_curv_unit = bohr2 时,程序会做相应单位换算(代码里会除以 bohr**2)。(wannier.org)wannier90_up-kslice-curv_x.pywannier90_up-kslice-curv_y.pywannier90_up-kslice-curv_z.py这三个是 自动生成的画图脚本:分别画 、、 的二维热力图。
-kslice-curv.dat 里按列读取(x/y/z 分量),并输出对应的 pdf(比如 wannier90_up-kslice-curv_x.pdf)。(wannier.org)就会出图(并保存成 pdf)。bashpython wannier90_up-kslice-curv_z.py
coord.dat 给的是二维投影坐标,不是 。postw90 在内部用的是
(源码就是这么生成的)。(wannier.org)
所以你可以用这个公式把每一行的 3D 重建出来,再和 curv.dat 拼成你自己的 mapping 表。
如果你把你当前的 kslice_corner / kslice_b1 / kslice_b2 / kslice_2dkmesh 贴一下,我可以按你的参数把“行号 → 3D k → Ω(k)”的 mapping 脚本写成可直接跑的版本。