2. 安装隔离依赖环境
Linux
使用新 Python 环境和合适的 PyTorch。源码声明 Python >=3.8,但解析后的依赖可能要求更高版本;审核示例以 Python 3.11 为目标,仍待实际执行。保存 pip freeze 及权重校验和。
python -m pip install torch
python -m pip install 'sevenn @ git+https://github.com/MDIL-SNU/SevenNet.git@209339d4eb4c1717f906c4cb715629159f00f88c' ase
python -m pip freeze
官方来源预期结果
记录的环境可导入 sevenn.calculator 和 ASE,不表示已取得数值结果。
3. 保存本审核编写的计算器示例
Linux
将随附 Python 代码保存为 sevennet0_relax.py。它基于官方接口在本次编写,不是上游测试结果。固定源码的 7net-0 别名指向 2024 年 7 月权重;明确使用 CPU,固定晶胞且输出目录不得已存在。
"""Authored review example using documented SevenNet/ASE APIs; NOT executed.
Sources: sevenn.calculator.SevenNetCalculator, ASE IO and BFGS documentation.
Fixed-cell geometry optimization only. No MD, reference DFT, or accuracy claim.
"""
import argparse
import json
from pathlib import Path
import numpy as np
from ase.io import read, write
from ase.optimize import BFGS
from sevenn.calculator import SevenNetCalculator
parser = argparse.ArgumentParser()
parser.add_argument("input_cif")
parser.add_argument("output_directory")
args = parser.parse_args()
atoms = read(args.input_cif)
if len(atoms) == 0 or not np.isfinite(atoms.positions).all():
raise ValueError("Empty structure or nonfinite coordinates")
if not atoms.pbc.all() or atoms.get_volume() <= 0:
raise ValueError("This example requires a fully periodic crystal with positive cell volume")
# The pinned SevenNet implementation resolves 7net-0 to its July 2024 checkpoint.
# The calculator checks each atomic number against the loaded model type_map.
atoms.calc = SevenNetCalculator(model="7net-0", device="cpu")
energy_initial = float(atoms.get_potential_energy())
forces_initial = atoms.get_forces()
if not np.isfinite(energy_initial) or not np.isfinite(forces_initial).all():
raise ValueError("Nonfinite initial energy or forces")
out = Path(args.output_directory)
out.mkdir(parents=True, exist_ok=False)
write(out / "initial.extxyz", atoms)
optimizer = BFGS(atoms, logfile=str(out / "optimization.log"), trajectory=str(out / "optimization.traj"))
# These are illustrative stopping settings, not upstream recommendations for all systems.
converged = bool(optimizer.run(fmax=0.05, steps=100))
energy_final = float(atoms.get_potential_energy())
forces_final = atoms.get_forces()
if not np.isfinite(energy_final) or not np.isfinite(forces_final).all():
raise ValueError("Nonfinite final energy or forces; inspect the partial output")
write(out / "relaxed.cif", atoms)
np.savez(out / "forces.npz", initial=forces_initial, final=forces_final)
record = {"model": "7net-0", "device": "cpu", "atom_count": len(atoms),
"elements": sorted(set(atoms.get_chemical_symbols())), "fixed_cell": True,
"energy_initial_eV": energy_initial, "energy_final_eV": energy_final,
"force_unit": "eV/Angstrom", "fmax_threshold_eV_per_Angstrom": 0.05,
"max_steps": 100, "converged": converged,
"final_max_force_eV_per_Angstrom": float(np.linalg.norm(forces_final, axis=1).max())}
(out / "results.json").write_text(json.dumps(record, indent=2) + "\n", encoding="utf-8")
print(json.dumps(record, indent=2))
if not converged:
raise SystemExit("Optimization reached its step limit; do not describe it as converged")
官方来源预期结果
配置在有限步数 BFGS 运行前检查原子类型、坐标和周期晶胞。