Skip to content

Commit 9d16216

Browse files
committed
feat: add neb
1 parent 97f5334 commit 9d16216

File tree

4 files changed

+130
-22
lines changed

4 files changed

+130
-22
lines changed

lambench/models/ase_models.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,17 @@ def evaluate(
207207

208208
assert task.test_data is not None
209209
return {"metrics": run_torsionnet(self, task.test_data)}
210+
elif task.task_name == "neb":
211+
from lambench.tasks.calculator.neb.neb import run_inference
212+
assert task.test_data is not None
213+
return {
214+
"metrics": run_inference(
215+
self,
216+
task.test_data,
217+
task.calculator_params.get("fmax", 0.01),
218+
task.calculator_params.get("steps", 500),
219+
)
220+
}
210221
else:
211222
raise NotImplementedError(f"Task {task.task_name} is not implemented.")
212223

lambench/models/models_config.yml

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -207,21 +207,36 @@
207207
show_finetune_task: True
208208
show_calculator_task: True
209209

210-
- model_name: dpa3_250307_v3_0_0_3M
210+
- model_name: dpa3_250415_v3_1_0_3M
211211
model_type: DP
212212
model_family: DP
213-
model_path: /bohr/lambench-model-55c1/v8/dpa3_250307_v3_0_0_3M/dp_dpa3_v3.0.0_0307_426w.pt
214-
virtualenv: *bohrium_image
213+
model_path: /bohr/lambench-model-55c1/v12/dpa3_250415_v3_1_0_3M/dp_dpa3_v3.1.0_0415_400w.pt
214+
virtualenv: registry.dp.tech/dptech/dp/native/prod-375/lambench:v2.11
215215
model_metadata:
216-
pretty_name: DPA-3.0-3M
217-
date_added: 2025-04-10
218-
model_description: DP 2025 Q1, 3M parameters
219-
num_parameters: 2592390
216+
pretty_name: DPA-3.1-3M
217+
date_added: 2025-05-13
218+
model_description: DP 2025 Q2, 16 layers with dynamic nnei.
219+
num_parameters: 3268689
220220
packages:
221-
deepmd-kit: P0131
222-
show_finetune_task: False
221+
deepmd-kit: P0414
222+
show_finetune_task: True
223223
show_calculator_task: True
224-
skip_tasks: [PropertyFinetuneTask]
224+
225+
# - model_name: dpa3_250307_v3_0_0_3M
226+
# model_type: DP
227+
# model_family: DP
228+
# model_path: /bohr/lambench-model-55c1/v8/dpa3_250307_v3_0_0_3M/dp_dpa3_v3.0.0_0307_426w.pt
229+
# virtualenv: *bohrium_image
230+
# model_metadata:
231+
# pretty_name: DPA-3.0-3M
232+
# date_added: 2025-04-10
233+
# model_description: DP 2025 Q1, 3M parameters
234+
# num_parameters: 2592390
235+
# packages:
236+
# deepmd-kit: P0131
237+
# show_finetune_task: False
238+
# show_calculator_task: True
239+
# skip_tasks: [PropertyFinetuneTask]
225240

226241
- model_name: mace_mp_0_medium
227242
model_type: ASE
@@ -275,18 +290,18 @@
275290
orb-models: 0.5.2
276291
show_calculator_task: True
277292

278-
- model_name: 7net-0
279-
model_type: ASE
280-
model_family: SevenNet
281-
virtualenv: *bohrium_image
282-
model_metadata:
283-
pretty_name: SevenNet-0
284-
date_added: 2025-04-10
285-
model_description: https://github.com/MDIL-SNU/SevenNet/blob/main/sevenn/pretrained_potentials/SevenNet_0__11Jul2024/checkpoint_sevennet_0.pth
286-
num_parameters: 842440
287-
packages:
288-
sevenn: 0.11.0
289-
show_calculator_task: True
293+
# - model_name: 7net-0
294+
# model_type: ASE
295+
# model_family: SevenNet
296+
# virtualenv: *bohrium_image
297+
# model_metadata:
298+
# pretty_name: SevenNet-0
299+
# date_added: 2025-04-10
300+
# model_description: https://github.com/MDIL-SNU/SevenNet/blob/main/sevenn/pretrained_potentials/SevenNet_0__11Jul2024/checkpoint_sevennet_0.pth
301+
# num_parameters: 842440
302+
# packages:
303+
# sevenn: 0.11.0
304+
# show_calculator_task: True
290305

291306
- model_name: 7net-l3i5
292307
model_type: ASE

lambench/tasks/calculator/calculator_tasks.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ inference_efficiency:
1515
torsionnet:
1616
test_data: /bohr/lambench-torsionnet-e4sc/v2/torsionnet500_wB97m
1717
calculator_params: null
18+
neb:
19+
test_data: /bohr/lambench-neb-b1ln/v1/OC20NEB-OOD
20+
calculator_params:
21+
fmax: 0.01
22+
steps: 500

lambench/tasks/calculator/neb/neb.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from lambench.models.ase_models import ASEModel
2+
from pathlib import Path
3+
import pandas as pd
4+
import numpy as np
5+
from tqdm import tqdm
6+
from ase.io import read
7+
from sklearn.metrics import mean_absolute_error
8+
9+
10+
def run_inference(
11+
model: ASEModel,
12+
test_data: Path,
13+
fmax: float,
14+
steps: int,
15+
) -> dict[str, float]:
16+
""" "
17+
This tests perform energy barrier prediction for 460 OOD NEB trajs in the OC20NEB dataset.
18+
19+
The label.csv file contains the ground truth energy barrier and dE for each trajectory.
20+
Each trajectory file contains 10 frames, and the first and last frames are the initial and final states.
21+
Using the ground truth energy label, the index of the transition state is determined.
22+
23+
We then perform structure optimization for the initial, final, and transition states and calculate the energy barrier and dE.
24+
"""
25+
result_df = pd.read_csv(Path(test_data, "label.csv"))
26+
result_df.sort_values("traj", inplace=True)
27+
result_df["pred_Ea"] = None
28+
result_df["pred_dE"] = None
29+
NUM_RECORDS = len(result_df)
30+
ERROR_THRESHOLD = 0.1 # counting Ea predtion error > 0.1 eV as failure
31+
32+
for idx, row in tqdm(result_df.iterrows()):
33+
traj_name = row["traj"]
34+
data = read(test_data, f"{traj_name}.traj", ":")
35+
energies = [frame.get_potential_energy() for frame in data]
36+
barrier_idx = np.argmax(energies)
37+
38+
initial, transition, final = data[0], data[barrier_idx], data[-1]
39+
relaxed_energy = []
40+
for atoms in [initial, transition, final]:
41+
atoms = ASEModel.run_ase_relaxation(
42+
atoms=atoms,
43+
calc=model.calc,
44+
fmax=fmax,
45+
steps=steps,
46+
fix_symmetry=False,
47+
relax_cell=False,
48+
)
49+
relaxed_energy.append(atoms.get_potential_energy())
50+
e_a, de = (
51+
relaxed_energy[1] - relaxed_energy[0],
52+
relaxed_energy[-1] - relaxed_energy[0],
53+
)
54+
result_df.at[idx, "pred_Ea"] = e_a
55+
result_df.at[idx, "pred_dE"] = de
56+
57+
result_df["type"] = result_df["traj"].apply(lambda x: x.split("_")[0])
58+
result_df["error"] = result_df.apply(
59+
lambda x: np.abs(x["pred_Ea"] - x["Ea"]), axis=1
60+
)
61+
type_percentages = (
62+
result_df[result_df["error"] > ERROR_THRESHOLD].groupby("type").size()
63+
/ result_df.groupby("type").size()
64+
* 100
65+
)
66+
type_percentages = type_percentages.round(2)
67+
results = type_percentages.to_dict()
68+
type_percentages.dropna(inplace=True)
69+
results["success_rate"] = len(type_percentages) / NUM_RECORDS * 100
70+
results["MAE_Ea"] = mean_absolute_error(
71+
result_df["Ea"], result_df["pred_Ea"]
72+
).round(2)
73+
results["MAE_dE"] = mean_absolute_error(
74+
result_df["dE"], result_df["pred_dE"]
75+
).round(2)
76+
77+
return results

0 commit comments

Comments
 (0)