Python 接口指南

July 27, 2026 · View on GitHub

Python frontend 提供两层接口:

  • NEPCalculator:面向 NumPy、结构列表和批计算;
  • NepAseCalculator:面向 ASE 的标准 calculator 工作流。

底层 Model 适合需要完全控制数组布局的调用方。一般用户从 NEPCalculator 或 ASE 开始即可。

安装

仅使用 NumPy 接口:

python -m pip install nep-adapters

同时使用 ASE:

python -m pip install 'nep-adapters[ase]'

预编译 wheel 支持 CPython 3.10–3.14。Linux x86_64 和 Windows x86_64 wheel 同时包含 CPU 与 CUDA 后端,不需要另外安装 CUDA Toolkit;使用 CUDA 仍需兼容的 NVIDIA 驱动和 GPU。macOS x86_64 与 arm64 wheel 只包含 CPU 后端。

从源码安装时,构建系统会自动查找 NVCC:找到时构建 CPU+CUDA,找不到时 只构建 CPU。

python -m pip install .

NEP_CUDA=1NEP_CUDA=0 可分别强制源码构建启用或禁用 CUDA。 NumPy 是必需依赖,ASE 是可选依赖。

第一次计算

from ase import Atoms
from nep_adapters import NEPCalculator

atoms = Atoms(
    "Fe2",
    positions=[[0.0, 0.0, 0.0], [1.43, 1.43, 1.43]],
    cell=[2.86, 2.86, 2.86],
    pbc=True,
)

with NEPCalculator("nep.txt", backend="cpu") as calculator:
    prediction = calculator.predict_structures([atoms])

print(prediction.energy)       # (nstructures,)
print(prediction.forces)       # (total_atoms, 3)
print(prediction.virials)      # (total_atoms, 9)

backend 只能显式选择 "cpu""cuda"。库没有 auto 后端,也不会在 CUDA 失败时回退到 CPU。

ASE calculator

from nep_adapters.ase import NepAseCalculator

atoms.calc = NepAseCalculator("nep.txt", backend="cpu")
energy = atoms.get_potential_energy()
forces = atoms.get_forces()
stress = atoms.get_stress()

普通 import nep_adapters 不会导入 ASE。只有使用 ASE 适配器时才需要安装 ase extra。

spin 模型也使用同一个 NepAseCalculator。结构必须提供 (natoms, 3) 的 vector spin;ASE 的 vector initial_magmoms 可直接使用,scalar initial_magmoms 不会被自动猜成方向。

核心计算接口保持 GPUMD 的 pressure-positive virial 约定。ASE 适配器只在边界处转换为 ASE 的能量-应变导数约定:

stress_ASE = -virial_total / volume
           = -num_atoms * structure_virials / volume

其中 structure_virials 是平均每原子 virial。这个负号转换不会改变 NumPy/C API 返回的原始 virial。

先检查模型和后端

from nep_adapters import backend_status, inspect_model

model_info = inspect_model("nep.txt")
print(model_info.model_type)
print(model_info.elements)
print(model_info.descriptor_dim)

cuda = backend_status("cuda")
print(cuda.available, cuda.reason)

inspect_model() 不执行预测,可用于在 UI 或批处理开始前确认模型类型、元素、cutoff、能力和 SHA256。backend_status("cuda") 会报告扩展、运行时、设备和显存状态,并通过一次内存分配、核函数启动、同步和结果回传验证 CUDA 计算链路。

普通 NEP 批计算

from nep_adapters import NEPCalculator

calculator = NEPCalculator("nep.txt", backend="cpu")
prediction = calculator.predict_structures(structures)

energies = prediction.energy
force_blocks = prediction.force_blocks()
virial_blocks = prediction.virial_blocks(mean=True)

兼容已有调用方的简写:

energies, force_blocks, virial_blocks = calculator.calculate(structures)

Prediction 的主要字段:

字段形状含义
energy(nstructures,)每个结构的总能量
potential(total_atoms,)拼接后的每原子势能
forces(total_atoms, 3)拼接后的每原子力
virials(total_atoms, 9)拼接后的每原子 virial
structure_virials(nstructures, 9)每个结构的平均每原子 virial

所有输出均为 float64。Python raw9 virial 顺序是:

xx, xy, xz, yx, yy, yz, zx, zy, zz

virial 的符号与 GPUMD 原生计算保持一致;如果调用方需要 ASE stress,必须按上一节的公式转换。

直接传 NumPy 数组

prediction = calculator.predict_arrays(
    types=types,              # int32, (total_atoms,)
    positions=positions,      # float64, (total_atoms, 3)
    boxes=boxes,              # float64, (nstructures, 9)
    atom_counts=atom_counts,  # int32, (nstructures,)
    pbc=(1, 1, 1),
)

types 是模型元素列表中的零基索引。当前 batch API 只支持全周期;显式传入非全周期或 None 会报错。

qNEP

qNEP 必须使用 charge 接口,普通 calculate() 会拒绝 charge 模型:

prediction = calculator.predict_charge_structures(structures)
print(prediction.charges)  # (total_atoms,)
print(prediction.becs)     # (total_atoms, 9)

energies, forces, virials, charges, becs = (
    calculator.calculate_charge(structures)
)

CPU 支持 charge/BEC。CUDA 支持 qNEP direct batch;PPPM 只有在构建时显式打开 NEP_ADAPTERS_CUDA_ENABLE_QNEP_PPPM=ON 才存在。qNEP CUDA batch 可用不代表 LAMMPS Kokkos 可用,后者当前明确拒绝。

spin NEP

spin 模型必须使用显式 spin 接口:

prediction = calculator.predict_spin_structures(structures, spins=spin_blocks)
print(prediction.mforces)

energies, forces, virials, mforces = calculator.calculate_spin(
    structures,
    spins=spin_blocks,
)

spins 可以是拼接后的 (total_atoms, 3) 数组,也可以是每个结构一个 (natoms, 3) block。结构自身的 spin / spins 数据和显式参数同时存在但不一致时,接口会拒绝歧义输入。

descriptor 和响应模型

普通、qNEP、dipole 和 polarizability 模型使用:

descriptors = calculator.predict_descriptors(structures)

spin 模型使用:

descriptors = calculator.predict_spin_descriptors(structures, spins=spin_blocks)

其他高层入口:

模型 / 计算接口
dipolepredict_dipoles()
polarizabilitypredict_polarizabilities()
仅 DFT-D3 修正predict_dftd3_structures()
NEP + DFT-D3predict_with_dftd3_structures()

dipole、polarizability 和 DFT-D3 当前只支持 CPU。DFT-D3 只接受普通非 spin、非 charge 势模型。

CUDA 显存预算

calculator = NEPCalculator("nep.txt", backend="cuda")

estimate = calculator.estimate_workspace(
    atom_capacity=100_000,
    structure_capacity=8,
)
print(estimate.total_bytes)

safe_limit = calculator.recommend_max_atoms()

atom_capacity 表示一个 batch 中最大单结构的原子数,不会把一个超大结构拆开。recommend_max_atoms() 只在 CUDA 后端有意义。

错误和取消

所有公共入口抛出 NepAdaptersError 的稳定子类,包括:

  • InvalidInputError
  • UnsupportedModelError
  • BackendUnavailableError
  • ModelLoadError
  • BackendRuntimeError
  • OutOfMemoryError
  • CancelledError

异常带有稳定的 code,并在适用时带 backendoperation。调用方应判断这些字段,不要匹配完整 native 错误文案。

计算运行时可从另一个 Python/UI 线程调用 calculator.cancel();取消不会返回部分结果。再次使用前调用 calculator.reset_cancel()

能力边界速查

能力CPUCUDA
普通 NEP支持NEP4/NEP5 支持
qNEP charge/BEC支持direct 支持;PPPM 需单独编译
spin NEP支持支持
dipole支持不支持
polarizability支持不支持
DFT-D3受限支持不支持

需要构建开发版或运行 Python CTest 时,见 构建与安装