dpdata标签存储与格式精度
用实际9帧Si数据比较HDF5、LMDB、n2p2、ASE轨迹和float32存储,给出终端转换与字段保留结果。
阅读本篇目录
把计算结果换一个文件后缀,并不意味着能量、力和virial都被保留下来。本例使用鸢算科技已计算并提取的9帧Si数据,每帧2个原子,实际比较五种标签存储方式;不重新运行电子结构计算。
1 下载并运行全部示例#
下载dpdata格式实操包,保存为dpdata-formats.zip。CPU即可运行:
python3 -m zipfile -e dpdata-formats.zip .
cd dpdata-format-workflows
bash setup.sh
bash run.sh
bash verify.sh
bash plot.sh
例程使用现有GPUMDkit环境中的Python 3.11.16、dpdata 1.1.0、NumPy、ASE、h5py、lmdb/msgpack和pymatgen,1个CPU线程。无需GPU。从登录节点提交时,也可在解压后使用sbatch job.slurm。
inputs/si-nine/是真实标签的DeepMD NumPy数据;results/保存本次所有转换文件,plots/保存实际误差图。再次运行相同完整输入会读取已有结果;更改数据时请保留旧目录,换新目录运行。原始数据的计算与提取流程见科学软件输出读取。
2 五种存储方式各保留什么#
| 本例实际格式 | 坐标、晶胞 | 能量、力 | virial | 主要用途 |
|---|---|---|---|---|
| DeepMD HDF5,float64 | 保留 | 保留 | 保留 | 把数据集中到一个HDF5文件 |
| DeepMD LMDB | 保留 | 保留 | 保留 | 按帧组织数据库数据 |
| n2p2 input.data | 保留,受文本位数影响 | 保留,使用原子单位 | 本例写入器不保存 | 与n2p2格式交换 |
| ASE trajectory | 保留 | 保留 | 由stress与体积换算保留 | 结合ASE进行轨迹处理 |
| DeepMD NumPy,float32 | 保留但发生舍入 | 保留但发生舍入 | 保留但发生舍入 | 需要较小数组时评估精度影响 |

图的前五行是本篇标签存储,后八行是结构格式转换。没有保留的字段不会用零补造。这里的virial单位为eV;它与stress的关系是virial = −体积 × stress,不能只改字段名。
3 直接在终端转换HDF5、LMDB和ASE轨迹#
下面从同一份9帧数据生成自己的文件:
source env.sh
"$YS_PY" - <<'PYCODE'
import dpdata
s = dpdata.LabeledSystem('inputs/si-nine', fmt='deepmd/npy')
s.to('deepmd/hdf5', 'my-si.h5', set_size=3)
s.to('deepmd/lmdb', 'my-si.lmdb', map_size=64 * 1024**2)
s.to('ase/traj', 'my-si.traj')
for fmt, path in [('deepmd/hdf5', 'my-si.h5'),
('deepmd/lmdb', 'my-si.lmdb'),
('ase/traj', 'my-si.traj')]:
t = dpdata.LabeledSystem(path, fmt=fmt)
print(fmt, 'frames=', len(t), 'atoms=', t.get_natoms())
print('first energy/eV=', t['energies'][0])
print('force shape=', t['forces'].shape)
PYCODE
三种回读都得到9帧、每帧2个Si。HDF5的set_size=3把本例分为三个数据块;LMDB的64 MiB映射空间仅针对这组小数据,大数据应按实际容量设置。LMDB按帧读取和多组成分组的概念见官方LMDB说明。
本例对HDF5与LMDB的五类数组逐点比较,无数值差异;ASE轨迹的virial最大差约4.44×10⁻¹⁶ eV。脚本还分别通过h5py、lmdb/msgpack和ASE读取原始内容,核对实际数组及stress的符号和体积换算。
4 n2p2的原子单位和文本精度#
source env.sh
"$YS_PY" - <<'PYCODE'
import dpdata
s = dpdata.LabeledSystem('inputs/si-nine', fmt='deepmd/npy')
s.to('n2p2', 'my-input.data')
t = dpdata.LabeledSystem('my-input.data', fmt='n2p2')
print('frames=', len(t))
print('energy/eV=', t['energies'][0])
print('virial present=', 'virials' in t.data)
PYCODE
head -n 9 my-input.data
第一帧会出现energy -0.398668。这个字段在本例dpdata写入器中是Hartree,不是eV;坐标与晶胞为Bohr,力为Hartree/Bohr。dpdata回读后再转换为Å、eV和eV/Å。
9帧往返后,最大能量差约1.13×10⁻⁵ eV,坐标差约2.47×10⁻⁷ Å,力差约2.50×10⁻⁷ eV/Å,来自输出位数与单位换算。文件中的原子电荷占位零并不是计算所得的Bader电荷;原始标签没有这项数据。本例使用周期Si,不能据此推断任意非周期或变原子数数据都能按相同方式保存。文件布局可参考n2p2配置格式。

本例float32的最大能量变化约4.00×10⁻⁷ eV,坐标变化约2.35×10⁻⁷ Å;程序逐点检查其是否等于真正的float32舍入结果。它是这一数据集的格式精度变化,不是DFT计算误差,也不是所有训练数据都可接受的统一标准。
5 查看本地格式入口与原图#
source env.sh
"$YS_PY" list_formats.py > format-list.csv
head -n 8 format-list.csv
bash plot.sh --reference
ls reference-plots/*.png
当前环境列出84个格式名称,对应51种实现,多个名称可以指向同一实现。列表显示的是读写接口;使用某个读取器还需要相应的真实原生文件及其依赖。本篇实际执行五个存储/精度分支,另八个结构分支见结构格式实操。接口选择见dpdata格式文档,以本例1.1.0环境和完整脚本为准。