GPAW专题

GPAW局部自旋约束实操

用H2演示局部自旋与总磁矩的区别,给出约束输入、实际自旋密度、区域积分和终端提取步骤。

更新于 2026-11-09约 6 分钟阅读按任务与环境选择适用配置
阅读本篇目录

局部电荷约束控制一个区域中的总电子数;局部自旋约束控制该区域中上、下自旋电子数之差。两者不是同一个参数。本例让H2的总磁矩保持为零,同时让第一个H附近的高斯分区具有+0.03或−0.03的局部自旋差,观察两个区域相反的极化。

1 下载与计算#

下载局部自旋约束实操包,保存为gpaw-spin.zip。从登录节点提交可在解压后使用sbatch job.slurm;已经分配到CPU资源时,直接执行:

python3 -m zipfile -e gpaw-spin.zip .
cd gpaw-constrained-spin
bash setup.sh
bash run.sh
bash verify.sh
bash plot.sh

例程使用GPAW 26.7.0 CPU构建,1 MPI进程、4线程。results/保存实际计算、网格与数值结果,plots/保存本次图片。setup.sh会展开并核对原图使用的参考网格;下载包中的压缩是字节无损的。

请使用完整附件,保留spin_compat.py。 它适配本例所用26.7.0 FD自旋势接口,只作用于当前示例计算器,不修改公共安装目录。不要仅复制run.py到其他版本环境中。本例不计算约束态力、跃迁率或自旋激发谱。

2 结构、总自旋与局部目标#

两个H分别位于(4,4,4.63)和(4,4,5.37) Å,键长0.740 Å,盒为8×8×10 Å,三个方向不周期。几何保持固定。

run.py中的主要设置为:

atoms = Atoms('H2',
              positions=[[4, 4, 4.63], [4, 4, 5.37]],
              cell=[8, 8, 10], pbc=False,
              magmoms=[0.03, -0.03])
base = GPAW(legacy_gpaw=True, mode='fd', h=0.25,
            xc='PBE', spinpol=True,
            occupations=FermiDirac(0.01, fixmagmom=True),
            convergence={'energy': 1e-7, 'density': 1e-6,
                         'eigenstates': 1e-9},
            maxiter=200, txt='SCF.txt')
compat.attach(base)  # run.py已按文件加载随包的兼容层
c = CDFT(base, atoms,
         spin_regions=[[0]], spins=[0.03],
         spin_coefs=[-1.5],
         mu={'H': 0.5}, Rc={'H': 20.0},
         method='BFGS',
         minimizer_options={'gtol': 1e-4, 'maxiter': 50},
         tol=1e-4, compute_forces=False, txt='CDFT.txt')
atoms.calc = c
energy = atoms.get_potential_energy()

fixmagmom=True配合初始磁矩之和为零,固定全体系的自旋差;spin_regions=[[0]]指定只约束第0号原子的分区。spins=[0.03]是分区电子数差,不是“这个原子的量子自旋S=0.03”。在本例约定下,它对应约0.03 μB的部分自旋磁矩。

spin_coefs是外层优化器的初始势系数,单位eV;它不是最终自旋值。mu为高斯宽度、Rc为高斯支持半径,单位Å。本小盒使用20 Å使高斯支持覆盖整个计算盒;这个数值不是其他材料的通用推荐值。

目标与宽度在PLAN.json的conditions中,几何和GPAW设置在run.py中。更换体系时,要一起检查边界、网格、自旋状态和区域定义,并在新示例目录中运行。

3 本集群实际结果#

分区目标/e 高斯宽度/Å 实际分区自旋差/e 约束密度的DFT能量/eV 最终势系数/eV
+0.03000 0.5 +0.02999284 −6.59271995 −0.86751470
−0.03000 0.5 −0.02999284 −6.59271995 +0.86751470
+0.03000 0.6 +0.02999867 −6.58611846 −1.30818709

全体系始终有2个电子,总磁矩接近零。相同宽度的正、负目标给出相同能量,实际差远小于1 meV;改变分区宽度后,即便目标相同,定义的约束态和所需势系数也会改变。

H2实际局部自旋密度和高斯分区

前两幅图是实际赝自旋密度n↑−n↓的切片,红、蓝代表相反符号;黑点是实际原子位置。右图是第一个H的高斯分区权重。

本例计算的局部量为高斯加权的赝自旋密度积分,再按GPAW cDFT的原子分区约定添加PAW增广修正。它不是Bader自旋、形式氧化态,也不能仅凭该局部数值认定实验自旋多重度。

局部自旋目标、区域积分和实际能量

表中能量使用c.Edft,表示约束后密度的DFT部分。c.Ecdft还带有所施加势的贡献;不要把这两个字段混用,也不要直接把不同分区的能量差当作完整实验激发能。

4 终端导出表格#

source env.sh
"$YS_PY" - <<'PYCODE'
import json, csv
from pathlib import Path
v = json.loads(Path('results/VALIDATION.json').read_text())
with open('local-spin.csv', 'w', newline='') as f:
    w = csv.writer(f)
    w.writerow(['target_e', 'width_A', 'region_spin_e',
                'DFT_energy_eV', 'coefficient_eV', 'total_spin_e'])
    for r in v['results']:
        w.writerow([r['spin_target_e'], r['gaussian_width_A'],
                    r['region_spin_e'], r['KS_constrained_energy_eV'],
                    r['lagrange_eV'], r['total_magnetization_e']])
        print(r['name'], r['region_spin_e'],
              r['total_magnetization_e'])
PYCODE

5 自己读取网格积分和重画原图#

下面直接读取某一条件的完整网格,算一次区域积分:

source env.sh
"$YS_PY" - <<'PYCODE'
import numpy as np
from pathlib import Path
f = sorted(Path('results').glob('*-FIELDS.npz'))[0]
d = np.load(f)
pseudo = (d['weight'] * d['pseudo_spin_density_bohr3']).sum()
pseudo *= float(d['grid_volume_bohr3'])
aug = d['augmentation_e'][0] - d['augmentation_e'][1]
print('pseudo spin integral =', pseudo)
print('PAW augmentation =', aug)
print('region spin =', pseudo + aug)
PYCODE
bash plot.sh --reference
ls reference-plots/*.png

归档图在reference-plots/,本次计算图在plots/。再次执行相同完整输入会读取现有结果;更换目标或模型后请保留旧结果,使用新目录,便于对照。

构建环境:GCC 13.3、HPC-X/OpenMPI 5、MKL 2023.2、Libxc 7.0.0,GPAW 26.7.0、PAW数据26.8.0,随包兼容层仅适配所注明CPU FD接口。区域约定见GPAW约束DFT说明;局部电荷的操作见约束电荷实操。

需要根据你的体系选择资源?联系讨论计算需求。实际可用软件与权限,以当前账户和运行环境为准。

查看配图

放大后可滚动查看细节,按 Esc 关闭。

100%查看原图 ↗