ASE专题

ASE结构等价比较实操

用Cu32比较整体旋转、平移、周期换位和原子换序,再识别单个原子的真实位移。

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

同一结构转成CIF、换一组晶轴或调整原子排序后,坐标矩阵可能完全不同。判断是否还是同一个周期结构,需要比较晶胞与原子环境,而非逐行坐标相等。本例在鸢算科技集群实际运行 ASE3.29.0 的SymmetryEquivalenceCheck,以未优化Cu32说明操作;只做几何比较,不计算能量或稳定相。

1 下载并运行#

下载全部输入、原生结构、脚本、原子对数据和高清图。ASE独立Python3.11环境,NumPy/SciPy/Matplotlib,单进程单线程,无GPU需求。

python3 -m zipfile -e ase-Cu32-structure-equivalence-wave313-*.zip .
cd ase-Cu32-structure-equivalence-wave313
bash preview.sh
bash run.sh

preview/从已保存结构重画;work/重新建模并运行原生比较,随后读取.traj、生成完整周期距离表和图。目录已存在时使用新的解压目录,保留旧结果。

cat work/native/DATA.json
cat work/results/VALIDATION.json
head -n 8 work/results/pair-distances.csv
ls work/native

2 准备三个具体结构#

模型 实际操作 原生严格比较
原始Cu32 3.6 Å常规FCC胞重复2×2×2,晶胞7.2 Å 参考
刚性变换 结构和晶胞一起绕z转37°,平移(0.4,0.5,0.6) Å,wrap后逆转原子顺序 等价True
局部位移 原胞和其他31个原子不变,第0号原子沿x移动0.2 Å 不等价False

完整的建模与原生比较可以直接复制到终端:

module purge
module load ase/3.29.0
python - <<'PYCODE'
import numpy as np
from ase.build import bulk
from ase.io import write
from ase.utils.structure_comparator import SymmetryEquivalenceCheck
original = bulk('Cu', 'fcc', a=3.6, cubic=True) * (2, 2, 2)
rotated = original.copy()
rotated.rotate(37, 'z', rotate_cell=True)
rotated.translate([0.4, 0.5, 0.6])
rotated.wrap()
rotated = rotated[np.arange(32)[::-1]]
displaced = original.copy()
displaced.positions[0] += [0.2, 0, 0]
settings = dict(angle_tol=0.1, ltol=0.001, stol=0.001,
                vol_tol=0.001, scale_volume=False, to_primitive=False)
# 比较器会变换内部结构表示,给它副本,保留自己的输入。
print(SymmetryEquivalenceCheck(**settings).compare(original.copy(), rotated.copy()))
print(SymmetryEquivalenceCheck(**settings).compare(original.copy(), displaced.copy()))
write('original.traj', original)
write('rotated.traj', rotated)
write('displaced.traj', displaced)
PYCODE

预期两行分别为True、False。旋转周期结构时别漏掉rotate_cell=True,否则旋转原子却保留原晶胞,不一定还是相同的周期结构。

3 比较前为什么必须先copy#

本例所用版本的原生比较步骤会变换传入结构的坐标或晶胞表示。使用compare(a.copy(), b.copy()),避免比较后再拿已经被改动的a、b去写自己的输入文件。这个细节对后续位移、缺陷和轨迹处理很重要。

angle_tol是角度容差,ltol、stol是相对几何尺度参数,不是力阈值或统一的Å误差;本例取严格的0.001并关闭体积缩放。scale_volume=False可避免将体积变化先缩放掉。to_primitive=False表示这里不先做原胞转换;实际比较不同超胞时,应先按所用工具和化学成分整理到一致的物理表示。

完整Cu32晶胞、整体旋转换序及单原子位移的实际结构

图中画出全部32个原子和晶胞,局部位移用红色标记。不同坐标表示不意味着新材料,单个原子的真实位移也不能因为化学式相同就忽略。

4 读取完整结构与周期距离#

包内.traj与FIELDS.npz保留完整精度的原子序号、坐标、晶胞;extxyz便于检查文本,读图和数值时优先用完整精度文件。

python - <<'PYCODE'
import numpy as np
from ase.io import read
atoms = read('work/native/rotated-permuted.traj')
print(atoms.get_chemical_formula(), atoms.cell.volume)
print(atoms.get_all_distances(mic=True).shape)
data = np.load('work/native/FIELDS.npz')
print(data.files)
PYCODE

本例完整32×32周期原子对距离在恢复原子映射后,刚性变换前后的最大差约 2.66×10⁻¹⁵ Å;单原子位移使某些距离实际改变约 0.2 Å。三种表示的体积均为 373.248 ų。因此同时检查了整个结构,未只比较一个键长。

独立说明脚本对本例立方胞及其刚性旋转枚举27个最近周期像;对任意极端倾斜晶胞,不把这个简化枚举当成通用最小镜像算法,直接使用ASE的get_all_distances(mic=True)或ase.geometry.find_mic等工具。

5 换成自己的两个结构#

python - <<'PYCODE'
from ase.io import read
from ase.utils.structure_comparator import SymmetryEquivalenceCheck
# 把路径换成自己的两个结构文件。
a = read('work/native/reference.traj')
b = read('work/native/rotated-permuted.traj')
compare = SymmetryEquivalenceCheck(scale_volume=False)
print('几何是否等价:', compare.compare(a.copy(), b.copy()))
print('原子数:', len(a), len(b))
print('化学式:', a.get_chemical_formula(), b.get_chemical_formula())
PYCODE

最后这个示例使用原生默认几何容差,比前面0.001的严格演示更宽松。实际使用时要根据热振动、优化残余和缺陷目的设置容差;不要为了得到True而一味放宽。几何等价也不自动证明相同电荷、自旋、占据、势函数或电子态,启动计算前还应核对这些设置。

继续看建模与格式转换、近邻和几何工具、晶胞与原子联合优化和电位–pH图。原生工具说明见ASE工具模块。

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

查看配图

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

100%查看原图 ↗