Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 76 additions & 25 deletions interatomic_potentials/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,81 @@ Machine-learning interatomic potentials (MLIP) bridge the gap between quantum-le

## 2.Models Matrix

| **Supported Functions** | **[CHGNet](./configs/chgnet/README.md)** | **[MatterSim](./configs/mattersim//README.md)** |
| ----------------------------------- | ---------------------------------------- | ----------------------------------------------- |
| **Forward Prediction** | | |
|  Energy | ✅ | ✅ |
|  Force | ✅ | ✅ |
|  Stress | ✅ | ✅ |
|  Magmom | ✅ | - |
| **ML Capabilities · Training** | | |
|  Single-GPU | ✅ | ✅ |
|  Distributed Train | ✅ | ✅ |
|  Mixed Precision | - | - |
|  Fine-tuning | ✅ | ✅ |
|  Uncertainty / Active-Learning | - | - |
|  Dynamic→Static | - | - |
|  Compiler CINN | - | - |
| **ML Capabilities · Predict** | | |
|  Distillation / Pruning | - | - |
|  Standard inference | ✅ | ✅ |
|  Distributed inference | - | - |
|  Compiler CINN | - | - |
| **Molecular Dynamic Interface** | | |
|  ASE | ✅ | ✅ |
| **Dataset** | | |
|  MPtrj | ✅ | 🚧 |
| **ML2DDB🌟** | ✅ | - |
| **Supported Functions** | **[CHGNet](./configs/chgnet/README.md)** | **[MatterSim](./configs/mattersim//README.md)** | **[SevenNet](./configs/sevennet/README.md)** |
| ----------------------------------- | ---------------------------------------- | ----------------------------------------------- | -------------------------------------------- |
| **Forward Prediction** | | | |
|  Energy | ✅ | ✅ | ✅ |
|  Force | ✅ | ✅ | ✅ |
|  Stress | ✅ | ✅ | - |
|  Magmom | ✅ | - | - |
| **ML Capabilities · Training** | | | |
|  Single-GPU | ✅ | ✅ | ✅ |
|  Distributed Train | ✅ | ✅ | - |
|  Mixed Precision | - | - | - |
|  Fine-tuning | ✅ | ✅ | ✅ |
|  Uncertainty / Active-Learning | - | - | - |
|  Dynamic→Static | - | - | - |
|  Compiler CINN | - | - | - |
| **ML Capabilities · Predict** | | | |
|  Distillation / Pruning | - | - | - |
|  Standard inference | ✅ | ✅ | ✅ |
|  Distributed inference | - | - | - |
|  Compiler CINN | - | - | - |
| **Molecular Dynamic Interface** | | | |
|  ASE | ✅ | ✅ | ✅ |
| **Dataset** | | | |
|  MPtrj | ✅ | 🚧 | - |
| **ML2DDB🌟** | ✅ | - | - |

**Notice**:🌟 represent originate research work published from paddlematerials toolkit

## 3.SevenNet Quick Start

### 3.1 Overview

SevenNet is a message-passing graph neural network for interatomic potential prediction. This implementation provides a pure PaddlePaddle version without external dependencies like e3nn.

### 3.2 Installation

```bash
# Install dependencies
pip install paddlepaddle>=3.0.0 ase numpy tqdm pyyaml
```

### 3.3 Training

```bash
# Navigate to interatomic_potentials directory
cd interatomic_potentials

# Run training with config file
python sevennet_train.py --config configs/sevennet/sevennet_hfo2.yaml
```

### 3.4 Inference

```bash
python sevennet_train.py --config configs/sevennet/sevennet_hfo2.yaml \
--output-dir ./output/sevennet_hfo2
```

### 3.5 Configuration

The configuration file includes:
- **Model parameters**: hidden_dim, num_message_layers, num_rbf, cutoff
- **Dataset parameters**: path, cutoff, valid_ratio
- **Training parameters**: epoch, batch_size, learning_rate

### 3.6 Test

```bash
# Run unit tests
pytest test/test_sevennet.py -v
```

### 3.7 Notes

- SevenNet uses message-passing architecture with Gaussian RBF for distance encoding
- Supports energy and force prediction
- Pure PaddlePaddle implementation, no PyTorch/e3nn dependencies
- Recommended for small to medium scale molecular systems
84 changes: 84 additions & 0 deletions interatomic_potentials/configs/sevennet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# SevenNet Model Configuration

## Overview

SevenNet is a message-passing graph neural network for interatomic potential prediction.

## Pretrained Models

SevenNet provides multiple pretrained models:

| Model | Description | Training Dataset | Performance (CPS) |
|-------|-------------|------------------|-------------------|
| **SevenNet-Omni** (Recommended) | Universal potential, 15 datasets | 15 open ab initio datasets | 0.849 |
| SevenNet-Omni-i8 | Higher capacity (Nlayer=8) | 15 datasets | 0.859 |
| SevenNet-Omni-i12 | Highest capacity (Nlayer=12) | 15 datasets | 0.873 |
| SevenNet-MF-ompa | Multi-fidelity learning | MPtrj, sAlex, OMat24 | 0.845 |
| SevenNet-omat | OMat24 only | OMat24 | κSRME: 0.221 |
| SevenNet-l3i5 | MPtrj with lmax=3 | MPtrj | 0.714 |
| SevenNet-0 | Fastest inference | MPtrj | F1: 0.67 |

## Using Pretrained Models

### Step 1: Download Model

When official provides URLs, download the pretrained model:

```python
from ppmat.utils import download

model_name = "sevennet_omni" # or other model name
model_path = download.get_weights_path_from_url(MODEL_REGISTRY[model_name])
```

### Step 2: Load Model

```python
import paddle
from ppmat.models import PurePaddleSevenNet

# Load checkpoint
state_dict = paddle.load("path/to/checkpoint.pdparams")

# Create model
model = PurePaddleSevenNet(
num_species=100,
hidden_dim=128,
num_message_layers=5,
num_rbf=32,
cutoff=5.0,
)

# Load weights
model.set_state_dict(state_dict)
model.eval()
```

### Step 3: Predict

```python
# Create graph from structure
graph = {
"z": paddle.to_tensor([1, 8, 1], dtype="int64"), # H, O, H
"pos": paddle.to_tensor([[0, 0, 0], [1, 0, 0], [0, 1, 0]], dtype="float32"),
"edge_index": paddle.to_tensor([[0, 1], [1, 0]], dtype="int64"),
}

# Predict
result = model(graph)
energy = result["total_energy"]
```

## Training Datasets

The official training datasets include:

- **MPtrj** (Materials Project Trajectory): https://figshare.com/articles/dataset/Materials_Project_Trjectory_MPtrj_Dataset/23713842
- **OMat24**: https://huggingface.co/datasets/fairchem/OMAT24
- **sAlex**: https://huggingface.co/datasets/fairchem/OMAT24

## References

- [SevenNet Official Repository](https://github.com/MDIL-SNU/SevenNet)
- [SevenNet Documentation](https://sevennet.readthedocs.io/)
- [Pretrained Models Guide](https://sevennet.readthedocs.io/en/latest/user_guide/pretrained.html)
42 changes: 42 additions & 0 deletions interatomic_potentials/configs/sevennet/sevennet_hfo2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
model:
type: "sevennet"
num_species: 100
hidden_dim: 32
num_message_layers: 3
num_rbf: 32
cutoff: 4.0

dataset:
type: "extxyz"
# 使用仓库内相对路径或用户自行指定
# 示例: 下载数据集后放在 data/hfo2.extxyz
path: "data/hfo2.extxyz"
cutoff: 4.0
valid_ratio: 0.1

dataloader:
batch_size: 2
shuffle: true
num_workers: 0

optimizer:
type: "adam"
lr: 0.001

lr_scheduler:
type: "constant"

loss:
type: "mse"
force_loss_weight: 0.1

trainer:
epoch: 2
per_epoch: 1
seed: 42
device: "auto"

log:
save_dir: "./output/sevennet_hfo2"
log_interval: 1
save_interval: 1
42 changes: 42 additions & 0 deletions interatomic_potentials/configs/sevennet/sevennet_hfo2_large.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
model:
type: "sevennet"
num_species: 100
hidden_dim: 128
num_message_layers: 5
num_rbf: 64
cutoff: 5.0

dataset:
type: "extxyz"
# 使用仓库内相对路径或用户自行指定
# 示例: 下载数据集后放在 data/hfo2.extxyz
path: "data/hfo2.extxyz"
cutoff: 5.0
valid_ratio: 0.1

dataloader:
batch_size: 4
shuffle: true
num_workers: 0

optimizer:
type: "adam"
lr: 0.001

lr_scheduler:
type: "constant"

loss:
type: "mse"
force_loss_weight: 0.1

trainer:
epoch: 10
per_epoch: 2
seed: 42
device: "auto"

log:
save_dir: "./output/sevennet_hfo2_large"
log_interval: 1
save_interval: 2
118 changes: 118 additions & 0 deletions interatomic_potentials/infer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PaddleMaterials - Interatomic Potentials Inference Script
推理入口:python infer.py --model model.pdparams --structure structure.extxyz
"""

import argparse
import os
import sys
import numpy as np
import paddle
from ase.io import read
from ase.neighborlist import neighbor_list

PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, PROJECT_ROOT)

from ppmat.models.sevennet import PurePaddleSevenNet


def parse_args():
parser = argparse.ArgumentParser(description="Infer interatomic potential model")
parser.add_argument("--model", type=str, required=True, help="Path to model checkpoint")
parser.add_argument("--structure", type=str, required=True, help="Path to structure file")
parser.add_argument("--cutoff", type=float, default=5.0, help="Cutoff radius")
return parser.parse_args()


def atoms_to_graph(atoms, cutoff):
positions = atoms.get_positions().astype("float32")
numbers = atoms.get_atomic_numbers().astype("int64")
i, j = neighbor_list("ij", atoms, cutoff)
edge_index = np.vstack([i, j]).astype("int64")

return {
"z": paddle.to_tensor(numbers, dtype="int64"),
"pos": paddle.to_tensor(positions, dtype="float32"),
"edge_index": paddle.to_tensor(edge_index, dtype="int64"),
}


def predict(model, atoms, cutoff, energy_mean, energy_std):
graph = atoms_to_graph(atoms, cutoff)
num_atoms = len(atoms)

with paddle.no_grad():
out = model(graph)
raw_total = float(out["total_energy"].numpy())
pred_total = raw_total * energy_std + energy_mean
pred_per_atom = pred_total / num_atoms

return pred_total, pred_per_atom


def main():
args = parse_args()

# 加载模型
print(f"Loading model: {args.model}")
checkpoint = paddle.load(args.model)
state_dict = checkpoint["model_state_dict"]
energy_mean = float(checkpoint.get("energy_mean", 0.0))
energy_std = float(checkpoint.get("energy_std", 1.0))

# 获取配置
config = checkpoint.get("config", {})
model_cfg = config.get("model", {})

# 创建模型
model = PurePaddleSevenNet(
num_species=model_cfg.get("num_species", 100),
hidden_dim=model_cfg.get("hidden_dim", 128),
num_message_layers=model_cfg.get("num_message_layers", 4),
num_rbf=model_cfg.get("num_rbf", 32),
cutoff=model_cfg.get("cutoff", args.cutoff),
)
model.set_state_dict(state_dict)
model.eval()

print(f"Model loaded successfully")
print(f"Energy mean: {energy_mean:.6f}, std: {energy_std:.6f}")

# 读取结构
print(f"\nReading structure: {args.structure}")
atoms_list = read(args.structure, index=":")
if not isinstance(atoms_list, list):
atoms_list = [atoms_list]
print(f"Loaded {len(atoms_list)} structures")

# 预测
print("\n=== Prediction Results ===")
for idx, atoms in enumerate(atoms_list):
pred_total, pred_per_atom = predict(model, atoms, args.cutoff, energy_mean, energy_std)

ref_energy = None
for key in ["y_energy", "energy", "free_energy", "total_energy"]:
if key in atoms.info:
try:
ref_energy = float(atoms.info[key])
break
except Exception:
pass

print(f"\nStructure {idx + 1}:")
print(f" Atoms: {len(atoms)}")
print(f" Predicted total energy: {pred_total:.6f} eV")
print(f" Predicted per-atom energy: {pred_per_atom:.6f} eV/atom")

if ref_energy is not None:
print(f" Reference energy: {ref_energy:.6f} eV")
print(f" Error: {abs(pred_total - ref_energy):.6f} eV")

print("\nInference completed!")


if __name__ == "__main__":
main()
Loading