Yuan (Cyrus) Chiang commited on
Commit
b7d94da
·
unverified ·
1 Parent(s): 28b7fa4

Add eSEN and update dependency versions (#58)

Browse files

* add prefect task flow script

* add esen diatomics

* separate matgl

* update installation script

* adjust test ci installation

* enforce `dgl==2.5.0`

* rollback torch to 2.4

* test first

* dgl 2.2.1

* dgl 2.2.1

* dgl 2.2.1

* no cache; cu124

* remove pin for dgl

* bump matgl version and update calculator api

* rollback orb to 0.4.0

* specify fairchem github repo as dep

* update uv version on ci

* fairchem

.github/README.md CHANGED
@@ -34,28 +34,41 @@ pip install mlip-arena
34
  > [!CAUTION]
35
  > We recommend clean build in a new virtual environment due to the compatibility issues between multiple popular MLIPs. We provide a single installation script using `uv` for minimal package conflicts and fast installation!
36
 
 
 
 
37
  **Linux**
38
 
39
  ```bash
40
  # (Optional) Install uv
41
  curl -LsSf https://astral.sh/uv/install.sh | sh
42
  source $HOME/.local/bin/env
 
 
 
 
43
  # One script uv pip installation
44
  bash scripts/install-linux.sh
45
  ```
46
 
47
- ```bash
48
  # Or from command line
49
  git clone https://github.com/atomind-ai/mlip-arena.git
50
  cd mlip-arena
51
- pip install torch==2.2.0
52
- bash scripts/install-pyg.sh
53
- bash scripts/install-dgl.sh
 
 
 
 
 
 
54
  pip install -e .[test]
55
  pip install -e .[mace]
56
  # DeePMD
57
  DP_ENABLE_TENSORFLOW=0 pip install -e .[deepmd]
58
- ```
59
 
60
  **Mac**
61
 
 
34
  > [!CAUTION]
35
  > We recommend clean build in a new virtual environment due to the compatibility issues between multiple popular MLIPs. We provide a single installation script using `uv` for minimal package conflicts and fast installation!
36
 
37
+ > [!CAUTION]
38
+ > To automatically download farichem OMat24 checkpoint, please make sure you have gained downloading access to their HuggingFace [***model repo***](https://huggingface.co/facebook/OMAT24) (not dataset repo), and login locally on your machine through `huggginface-cli login` (see [HF hub authentication](https://huggingface.co/docs/huggingface_hub/en/quick-start#authentication))
39
+
40
  **Linux**
41
 
42
  ```bash
43
  # (Optional) Install uv
44
  curl -LsSf https://astral.sh/uv/install.sh | sh
45
  source $HOME/.local/bin/env
46
+
47
+ git clone https://github.com/atomind-ai/mlip-arena.git
48
+ cd mlip-arena
49
+
50
  # One script uv pip installation
51
  bash scripts/install-linux.sh
52
  ```
53
 
54
+ <!-- ```bash
55
  # Or from command line
56
  git clone https://github.com/atomind-ai/mlip-arena.git
57
  cd mlip-arena
58
+
59
+ TORCH=2.4
60
+ CUDA=cu124
61
+ pip install torch==${TORCH}.0
62
+ pip install torch-scatter torch-sparse -f https://data.pyg.org/whl/torch-${TORCH}.0+${CUDA}.html
63
+ pip install dgl -f https://data.dgl.ai/wheels/torch-${TORCH}/${CUDA}/repo.html
64
+ pip install -e .[fairchem] --no-deps
65
+ pip install -e .[orb]
66
+ pip install -e .[matgl]
67
  pip install -e .[test]
68
  pip install -e .[mace]
69
  # DeePMD
70
  DP_ENABLE_TENSORFLOW=0 pip install -e .[deepmd]
71
+ ``` -->
72
 
73
  **Mac**
74
 
.github/workflows/test.yaml CHANGED
@@ -24,8 +24,9 @@ jobs:
24
  uses: actions/checkout@v4
25
 
26
  - name: Install uv
27
- uses: astral-sh/setup-uv@v4
28
  with:
 
29
  enable-cache: true
30
  cache-dependency-glob: "pyproject.toml"
31
 
@@ -36,15 +37,7 @@ jobs:
36
 
37
  - name: Install dependencies
38
  run: |
39
- TORCH=2.2
40
- CUDA=cu121
41
- uv pip install torch==${TORCH}.0
42
- uv pip install torch-scatter -f https://data.pyg.org/whl/torch-${TORCH}.0+${CUDA}.html
43
- uv pip install torch-sparse -f https://data.pyg.org/whl/torch-${TORCH}.0+${CUDA}.html
44
- uv pip install dgl -f https://data.dgl.ai/wheels/torch-${TORCH}/${CUDA}/repo.html
45
- uv pip install -e .[test]
46
- uv pip install -e .[mace]
47
- uv pip install -e .[deepmd]
48
 
49
  - name: List dependencies
50
  run: pip list
 
24
  uses: actions/checkout@v4
25
 
26
  - name: Install uv
27
+ uses: astral-sh/setup-uv@v6
28
  with:
29
+ version: "latest"
30
  enable-cache: true
31
  cache-dependency-glob: "pyproject.toml"
32
 
 
37
 
38
  - name: Install dependencies
39
  run: |
40
+ bash scripts/install-linux.sh
 
 
 
 
 
 
 
 
41
 
42
  - name: List dependencies
43
  run: pip list
examples/mof/classification/classification.py CHANGED
@@ -60,7 +60,7 @@ def save_result(
60
  # Orchestrate your awesome dask workflow runner
61
 
62
  nodes_per_alloc = 1
63
- gpus_per_alloc = 4
64
  ntasks = 1
65
 
66
  cluster_kwargs = dict(
@@ -68,7 +68,7 @@ cluster_kwargs = dict(
68
  memory="64 GB",
69
  shebang="#!/bin/bash",
70
  account="m3828",
71
- walltime="01:30:00",
72
  job_mem="0",
73
  job_script_prologue=[
74
  "source ~/.bashrc",
@@ -82,7 +82,7 @@ cluster_kwargs = dict(
82
  f"-N {nodes_per_alloc}",
83
  "-C gpu",
84
  f"-G {gpus_per_alloc}",
85
- "--exclusive",
86
  ],
87
  )
88
 
@@ -122,7 +122,7 @@ def run_all():
122
 
123
  for model, row in tqdm(itertools.product(MLIPEnum, load_row_from_df("input.pkl"))):
124
 
125
- if model.name not in ["MACE-MPA", "MatterSim", "SevenNet", "M3GNet", "CHGNet", "ORBv2"]:
126
  continue
127
 
128
  fpath = Path(f"{model.name}.pkl")
 
60
  # Orchestrate your awesome dask workflow runner
61
 
62
  nodes_per_alloc = 1
63
+ gpus_per_alloc = 1
64
  ntasks = 1
65
 
66
  cluster_kwargs = dict(
 
68
  memory="64 GB",
69
  shebang="#!/bin/bash",
70
  account="m3828",
71
+ walltime="04:00:00",
72
  job_mem="0",
73
  job_script_prologue=[
74
  "source ~/.bashrc",
 
82
  f"-N {nodes_per_alloc}",
83
  "-C gpu",
84
  f"-G {gpus_per_alloc}",
85
+ # "--exclusive",
86
  ],
87
  )
88
 
 
122
 
123
  for model, row in tqdm(itertools.product(MLIPEnum, load_row_from_df("input.pkl"))):
124
 
125
+ if model.name not in ["MACE-MPA", "MatterSim", "SevenNet", "M3GNet", "ORBv2"]:
126
  continue
127
 
128
  fpath = Path(f"{model.name}.pkl")
mlip_arena/models/__init__.py CHANGED
@@ -42,7 +42,7 @@ for model, metadata in REGISTRY.items():
42
  f"{__package__}.{metadata['module']}.{metadata['family']}"
43
  )
44
  MLIPMap[model] = getattr(module, metadata["class"])
45
- except (ModuleNotFoundError, AttributeError, ValueError) as e:
46
  logger.warning(e)
47
  continue
48
 
 
42
  f"{__package__}.{metadata['module']}.{metadata['family']}"
43
  )
44
  MLIPMap[model] = getattr(module, metadata["class"])
45
+ except (ModuleNotFoundError, AttributeError, ValueError, ImportError) as e:
46
  logger.warning(e)
47
  continue
48
 
mlip_arena/models/externals/fairchem.py CHANGED
@@ -10,6 +10,33 @@ from huggingface_hub import hf_hub_download
10
  with open(Path(__file__).parents[1] / "registry.yaml", encoding="utf-8") as f:
11
  REGISTRY = yaml.safe_load(f)
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  class eqV2(OCPCalculator):
14
  def __init__(
15
  self,
 
10
  with open(Path(__file__).parents[1] / "registry.yaml", encoding="utf-8") as f:
11
  REGISTRY = yaml.safe_load(f)
12
 
13
+
14
+ class eSEN(OCPCalculator):
15
+ def __init__(
16
+ self,
17
+ checkpoint=REGISTRY["eSEN"]["checkpoint"],
18
+ cache_dir=None,
19
+ cpu=False, # TODO: cannot assign device
20
+ seed=0,
21
+ **kwargs,
22
+ ) -> None:
23
+
24
+ # https://huggingface.co/facebook/OMAT24/resolve/main/esen_30m_oam.pt
25
+
26
+ checkpoint_path = hf_hub_download(
27
+ "fairchem/OMAT24",
28
+ filename=checkpoint,
29
+ revision="13ab5b8d71af67bd1c83fbbf53250c82cd87f506",
30
+ cache_dir=cache_dir
31
+ )
32
+ kwargs.pop("device", None)
33
+ super().__init__(
34
+ checkpoint_path=checkpoint_path,
35
+ cpu=cpu,
36
+ seed=seed,
37
+ **kwargs,
38
+ )
39
+
40
  class eqV2(OCPCalculator):
41
  def __init__(
42
  self,
mlip_arena/models/externals/matgl.py CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
3
  import matgl
4
  import torch
5
  from matgl.ext.ase import PESCalculator
 
6
 
7
 
8
  class M3GNet(PESCalculator):
@@ -11,8 +12,10 @@ class M3GNet(PESCalculator):
11
  checkpoint="M3GNet-MP-2021.2.8-PES",
12
  # TODO: cannot assign device
13
  state_attr: torch.Tensor | None = None,
 
14
  stress_weight: float = 1.0,
 
15
  **kwargs,
16
  ) -> None:
17
  potential = matgl.load_model(checkpoint)
18
- super().__init__(potential, state_attr, stress_weight, **kwargs)
 
3
  import matgl
4
  import torch
5
  from matgl.ext.ase import PESCalculator
6
+ from typing import Literal
7
 
8
 
9
  class M3GNet(PESCalculator):
 
12
  checkpoint="M3GNet-MP-2021.2.8-PES",
13
  # TODO: cannot assign device
14
  state_attr: torch.Tensor | None = None,
15
+ stress_unit: Literal["eV/A3", "GPa"] = "GPa",
16
  stress_weight: float = 1.0,
17
+ use_voigt: bool = False,
18
  **kwargs,
19
  ) -> None:
20
  potential = matgl.load_model(checkpoint)
21
+ super().__init__(potential, state_attr, stress_unit, stress_weight, use_voigt, **kwargs)
mlip_arena/models/registry.yaml CHANGED
@@ -192,6 +192,29 @@ MACE-MPA:
192
  npt: true
193
  license: MIT
194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  EquiformerV2(OC22):
196
  module: externals
197
  class: EquiformerV2
 
192
  npt: true
193
  license: MIT
194
 
195
+ eSEN:
196
+ module: externals
197
+ class: eSEN
198
+ family: fairchem
199
+ package: fairchem-core==1.9.0
200
+ checkpoint: esen_30m_oam.pt
201
+ username: fairchem # HF handle
202
+ last-update: 2025-04-21
203
+ datetime: 2025-04-21
204
+ datasets:
205
+ - OMat
206
+ - MPTrj
207
+ - Alexandria
208
+ gpu-tasks:
209
+ - homonuclear-diatomics
210
+ prediction: EFS
211
+ nvt: true
212
+ npt: false # https://github.com/FAIR-Chem/fairchem/issues/888, https://github.com/atomind-ai/mlip-arena/issues/17
213
+ date: 2025-04-14
214
+ github: https://github.com/FAIR-Chem/fairchem
215
+ doi: https://arxiv.org/abs/2502.12147
216
+ license: Modified Apache-2.0 (Meta)
217
+
218
  EquiformerV2(OC22):
219
  module: externals
220
  class: EquiformerV2
mlip_arena/tasks/diatomics/analysis.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+ from ase.data import chemical_symbols
6
+ from ase.io import read
7
+ from scipy import stats
8
+ from scipy.interpolate import UnivariateSpline
9
+ from tqdm.auto import tqdm
10
+
11
+ from mlip_arena.models import REGISTRY, MLIPEnum
12
+
13
+ for model in MLIPEnum:
14
+
15
+ df = pd.DataFrame(
16
+ columns=[
17
+ "name",
18
+ "method",
19
+ "R",
20
+ "E",
21
+ "F",
22
+ "S^2",
23
+ "force-flip-times",
24
+ "force-total-variation",
25
+ "force-jump",
26
+ "energy-diff-flip-times",
27
+ "energy-grad-norm-max",
28
+ "energy-jump",
29
+ "energy-total-variation",
30
+ "tortuosity",
31
+ "conservation-deviation",
32
+ "spearman-descending-force",
33
+ "spearman-ascending-force",
34
+ "spearman-repulsion-energy",
35
+ "spearman-attraction-energy",
36
+ "pbe-energy-mae",
37
+ "pbe-force-mae",
38
+ ]
39
+ )
40
+
41
+ for symbol in tqdm(chemical_symbols[1:]):
42
+ da = symbol + symbol
43
+
44
+ out_dir = Path(model.name)
45
+
46
+ traj_fpath = out_dir / f"{str(da)}.extxyz"
47
+
48
+ if traj_fpath.exists():
49
+ traj = read(traj_fpath, index=":")
50
+ else:
51
+ continue
52
+
53
+ Rs, Es, Fs, S2s = [], [], [], []
54
+ for atoms in traj:
55
+ vec = atoms.positions[1] - atoms.positions[0]
56
+ r = np.linalg.norm(vec)
57
+ e = atoms.get_potential_energy()
58
+ f = np.inner(vec / r, atoms.get_forces()[1])
59
+ # s2 = np.mean(np.power(atoms.get_magnetic_moments(), 2))
60
+
61
+ Rs.append(r)
62
+ Es.append(e)
63
+ Fs.append(f)
64
+ # S2s.append(s2)
65
+
66
+ rs = np.array(Rs)
67
+ es = np.array(Es)
68
+ fs = np.array(Fs)
69
+
70
+ # sort interatomic distances and align to zero at far field
71
+ indices = np.argsort(rs)[::-1]
72
+ rs = rs[indices]
73
+ es = es[indices]
74
+ eshift = es[0]
75
+ es -= eshift
76
+ fs = fs[indices]
77
+
78
+ iminf = np.argmin(fs)
79
+ imine = np.argmin(es)
80
+
81
+ de_dr = np.gradient(es, rs)
82
+ d2e_dr2 = np.gradient(de_dr, rs)
83
+
84
+ # avoid numerical sensitity close to zero
85
+ rounded_fs = np.copy(fs)
86
+ rounded_fs[np.abs(rounded_fs) < 1e-2] = 0 # 10meV/A
87
+ fs_sign = np.sign(rounded_fs)
88
+ mask = fs_sign != 0
89
+ rounded_fs = rounded_fs[mask]
90
+ fs_sign = fs_sign[mask]
91
+ f_flip = np.diff(fs_sign) != 0
92
+
93
+ fdiff = np.diff(fs)
94
+ fdiff_sign = np.sign(fdiff)
95
+ mask = fdiff_sign != 0
96
+ fdiff = fdiff[mask]
97
+ fdiff_sign = fdiff_sign[mask]
98
+ fdiff_flip = np.diff(fdiff_sign) != 0
99
+ fjump = (
100
+ np.abs(fdiff[:-1][fdiff_flip]).sum() + np.abs(fdiff[1:][fdiff_flip]).sum()
101
+ )
102
+
103
+ ediff = np.diff(es)
104
+ ediff[np.abs(ediff) < 1e-3] = 0 # 1meV
105
+ ediff_sign = np.sign(ediff)
106
+ mask = ediff_sign != 0
107
+ ediff = ediff[mask]
108
+ ediff_sign = ediff_sign[mask]
109
+ ediff_flip = np.diff(ediff_sign) != 0
110
+ ejump = (
111
+ np.abs(ediff[:-1][ediff_flip]).sum() + np.abs(ediff[1:][ediff_flip]).sum()
112
+ )
113
+
114
+ try:
115
+ pbe_traj = read(f"./vasp/{da}/PBE.extxyz", index=":")
116
+
117
+ pbe_rs, pbe_es, pbe_fs = [], [], []
118
+
119
+ for atoms in pbe_traj:
120
+ vec = atoms.positions[1] - atoms.positions[0]
121
+ r = np.linalg.norm(vec)
122
+ pbe_rs.append(r)
123
+ pbe_es.append(atoms.get_potential_energy())
124
+ pbe_fs.append(np.inner(vec / r, atoms.get_forces()[1]))
125
+
126
+ pbe_rs = np.array(pbe_rs)
127
+ pbe_es = np.array(pbe_es)
128
+ pbe_fs = np.array(pbe_fs)
129
+
130
+ indices = np.argsort(pbe_rs)
131
+ pbe_rs = pbe_rs[indices]
132
+ pbe_es = pbe_es[indices]
133
+ pbe_fs = pbe_fs[indices]
134
+
135
+ pbe_es -= pbe_es[-1]
136
+
137
+ xs = np.linspace(pbe_rs.min(), pbe_rs.max(), int(1e3))
138
+
139
+ cs = UnivariateSpline(pbe_rs, pbe_es, s=0)
140
+ pbe_energy_mae = np.mean(np.abs(es - cs(rs)))
141
+
142
+ cs = UnivariateSpline(pbe_rs, pbe_fs, s=0)
143
+ pbe_force_mae = np.mean(np.abs(fs - cs(rs)))
144
+ except Exception as e:
145
+ print(e)
146
+ pbe_energy_mae = None
147
+ pbe_force_mae = None
148
+
149
+ conservation_deviation = np.mean(np.abs(fs + de_dr))
150
+
151
+ etv = np.sum(np.abs(np.diff(es)))
152
+
153
+ data = {
154
+ "name": da,
155
+ "method": model.name,
156
+ "R": rs,
157
+ "E": es + eshift,
158
+ "F": fs,
159
+ "S^2": S2s,
160
+ "force-flip-times": np.sum(f_flip),
161
+ "force-total-variation": np.sum(np.abs(np.diff(fs))),
162
+ "force-jump": fjump,
163
+ "energy-diff-flip-times": np.sum(ediff_flip),
164
+ "energy-grad-norm-max": np.max(np.abs(de_dr)),
165
+ "energy-jump": ejump,
166
+ # "energy-grad-norm-mean": np.mean(de_dr_abs),
167
+ "energy-total-variation": etv,
168
+ "tortuosity": etv / (abs(es[0] - es.min()) + (es[-1] - es.min())),
169
+ "conservation-deviation": conservation_deviation,
170
+ "spearman-descending-force": stats.spearmanr(
171
+ rs[iminf:], fs[iminf:]
172
+ ).statistic,
173
+ "spearman-ascending-force": stats.spearmanr(
174
+ rs[:iminf], fs[:iminf]
175
+ ).statistic,
176
+ "spearman-repulsion-energy": stats.spearmanr(
177
+ rs[imine:], es[imine:]
178
+ ).statistic,
179
+ "spearman-attraction-energy": stats.spearmanr(
180
+ rs[:imine], es[:imine]
181
+ ).statistic,
182
+ "pbe-energy-mae": pbe_energy_mae,
183
+ "pbe-force-mae": pbe_force_mae,
184
+ }
185
+
186
+ df = pd.concat([df, pd.DataFrame([data])], ignore_index=True)
187
+
188
+ json_fpath = Path(REGISTRY[model.name]["family"]) / "homonuclear-diatomics.json"
189
+
190
+ if json_fpath.exists():
191
+ df0 = pd.read_json(json_fpath)
192
+ df = pd.concat([df0, df], ignore_index=True)
193
+ df.drop_duplicates(inplace=True, subset=["name", "method"], keep="last")
194
+
195
+ df.to_json(json_fpath, orient="records")
196
+
197
+ json_fpath = Path(model.name) / "homonuclear-diatomics.json"
198
+ df.to_json(json_fpath, orient="records")
mlip_arena/tasks/diatomics/fairchem/homonuclear-diatomics.json CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:06fe63898d03644e491ef12e275884c110cf993b8182403408d65fdd23e51816
3
- size 2136895
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5f955a5e08dbb9be3d0a04f06bd4cf93ac63a6a401132a7e74e971365133472a
3
+ size 4286019
mlip_arena/tasks/diatomics/run.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import itertools
2
+ from pathlib import Path
3
+
4
+ import numpy as np
5
+ from ase import Atom, Atoms
6
+ from ase.calculators.calculator import BaseCalculator
7
+ from ase.data import chemical_symbols, covalent_radii, vdw_alvarez
8
+ from ase.io import read, write
9
+ from prefect import flow, task
10
+ from tqdm.auto import tqdm
11
+
12
+ from mlip_arena.models import REGISTRY, MLIPEnum
13
+ from mlip_arena.tasks.utils import get_calculator
14
+
15
+
16
+ @task
17
+ def homonuclear_diatomics(symbol: str, calculator: BaseCalculator, out_dir: Path):
18
+ """
19
+ Calculate potential energy curves for homonuclear diatomic molecules.
20
+
21
+ This function computes the potential energy of a diatomic molecule (two atoms of
22
+ the same element) across a range of interatomic distances. The distance range is
23
+ automatically determined from the covalent and van der Waals radii of the element.
24
+
25
+ Args:
26
+ symbol: Chemical symbol of the atom (e.g., 'H', 'O', 'Fe')
27
+ calculator: ASE calculator object used to compute the potential energies. Could be VASP, MLIP, etc.
28
+
29
+ Returns:
30
+ None: Results are saved as trajectory files in a directory structure:
31
+ /{model_family}/{element_pair}/{model_name}.extxyz
32
+
33
+ Note:
34
+ - Minimum distance is set to 0.9× the covalent radius
35
+ - Maximum distance is set to 3.1× the van der Waals radius (or 6 Å if unknown)
36
+ - Distance step size is fixed at 0.01 Å
37
+ - If an existing trajectory file is found, the calculation will resume from where it left off
38
+ - The atoms are placed in a periodic box large enough to avoid self-interaction
39
+ """
40
+
41
+ atom = Atom(symbol)
42
+ rmin = 0.9 * covalent_radii[atom.number]
43
+ rvdw = (
44
+ vdw_alvarez.vdw_radii[atom.number]
45
+ if atom.number < len(vdw_alvarez.vdw_radii)
46
+ else np.nan
47
+ )
48
+ rmax = 3.1 * rvdw if not np.isnan(rvdw) else 6
49
+ rstep = 0.01
50
+ npts = int((rmax - rmin) / rstep)
51
+
52
+ rs = np.linspace(rmin, rmax, npts)
53
+ es = np.zeros_like(rs)
54
+
55
+ da = symbol + symbol
56
+
57
+ out_dir.mkdir(parents=True, exist_ok=True)
58
+
59
+ skip = 0
60
+
61
+ a = 5 * rmax
62
+ r = rs[0]
63
+
64
+ positions = [
65
+ [a / 2 - r / 2, a / 2, a / 2],
66
+ [a / 2 + r / 2, a / 2, a / 2],
67
+ ]
68
+
69
+ traj_fpath = out_dir / f"{da!s}.extxyz"
70
+
71
+ if traj_fpath.exists():
72
+ traj = read(traj_fpath, index=":")
73
+ skip = len(traj)
74
+ atoms = traj[-1]
75
+ else:
76
+ # Create the unit cell with two atoms
77
+ atoms = Atoms(
78
+ da,
79
+ positions=positions,
80
+ # magmoms=magmoms,
81
+ cell=[a, a + 0.001, a + 0.002],
82
+ pbc=False,
83
+ )
84
+
85
+ atoms.calc = calculator
86
+
87
+ for i, r in enumerate(tqdm(rs)):
88
+ if i < skip:
89
+ continue
90
+
91
+ positions = [
92
+ [a / 2 - r / 2, a / 2, a / 2],
93
+ [a / 2 + r / 2, a / 2, a / 2],
94
+ ]
95
+
96
+ # atoms.set_initial_magnetic_moments(magmoms)
97
+ atoms.set_positions(positions)
98
+ es[i] = atoms.get_potential_energy()
99
+ write(traj_fpath, atoms, append="a")
100
+
101
+
102
+ @flow
103
+ def submit_homonuclear_diatomics():
104
+ futures = []
105
+ for symbol, model in itertools.product(
106
+ chemical_symbols[1:],
107
+ MLIPEnum,
108
+ ):
109
+ if "homonuclear-diatomics" not in REGISTRY[model.name].get("gpu-tasks", []):
110
+ continue
111
+
112
+ out_dir = Path(__file__).parent / model.name
113
+
114
+ calculator = get_calculator(model)
115
+
116
+ # if not (out_dir / "homonuclear-diatomics.json").exists():
117
+ future = homonuclear_diatomics.submit(
118
+ symbol,
119
+ calculator,
120
+ out_dir=out_dir,
121
+ )
122
+ futures.append(future)
123
+
124
+ return [f.result(raise_on_failure=False) for f in futures]
125
+
126
+
127
+ if __name__ == "__main__":
128
+ submit_homonuclear_diatomics.with_options(
129
+ # task_runner=DaskTaskRunner(address=client.scheduler.address),
130
+ log_prints=True,
131
+ )()
pyproject.toml CHANGED
@@ -47,19 +47,14 @@ app = [
47
  "plotly",
48
  ]
49
  test = [
50
- "torch==2.2.0",
51
  "torch_dftd==0.4.0",
52
- "nvidia-ml-py==12.560.30",
53
  "e3nn==0.5.0",
54
- "matgl==1.1.2",
55
- # "dgl==2.4.0",
56
  "chgnet==0.3.8",
57
- "fairchem-core==1.2.0",
58
  "sevenn==0.9.3.post1",
59
- "orb-models==0.4.0",
60
- "pynanoflann@git+https://github.com/dwastberg/pynanoflann#egg=af434039ae14bedcbb838a7808924d6689274168",
61
  "alignn==2024.5.27",
62
- "mattersim==1.0.0rc9",
63
  "torchani==2.2.4",
64
  "pytest",
65
  "pytest-xdist",
@@ -69,7 +64,18 @@ test = [
69
  "streamlit==1.43.2"
70
  ]
71
  mace = [
72
- "mace-torch==0.3.9",
 
 
 
 
 
 
 
 
 
 
 
73
  ]
74
  deepmd = [
75
  "torch==2.2.0",
 
47
  "plotly",
48
  ]
49
  test = [
50
+ "torch==2.4.0",
51
  "torch_dftd==0.4.0",
 
52
  "e3nn==0.5.0",
53
+ "dgl",
 
54
  "chgnet==0.3.8",
 
55
  "sevenn==0.9.3.post1",
 
 
56
  "alignn==2024.5.27",
57
+ "mattersim==1.1.2",
58
  "torchani==2.2.4",
59
  "pytest",
60
  "pytest-xdist",
 
64
  "streamlit==1.43.2"
65
  ]
66
  mace = [
67
+ "mace-torch==0.3.12",
68
+ ]
69
+ matgl = [
70
+ "matgl==1.2.6",
71
+ ]
72
+ fairchem = [
73
+ "hydra-core",
74
+ "fairchem-core@git+https://github.com/facebookresearch/fairchem.git#subdirectory=packages/fairchem-core",
75
+ ]
76
+ orb = [
77
+ "orb-models==0.4.0",
78
+ "pynanoflann@git+https://github.com/dwastberg/pynanoflann#egg=af434039ae14bedcbb838a7808924d6689274168",
79
  ]
80
  deepmd = [
81
  "torch==2.2.0",
scripts/install-linux.sh CHANGED
@@ -1,8 +1,10 @@
1
- TORCH=2.2
2
- CUDA=cu121
3
  uv pip install torch==${TORCH}.0
4
- uv pip install torch-scatter -f https://data.pyg.org/whl/torch-${TORCH}.0+${CUDA}.html
5
- uv pip install torch-sparse -f https://data.pyg.org/whl/torch-${TORCH}.0+${CUDA}.html
6
  uv pip install dgl -f https://data.dgl.ai/wheels/torch-${TORCH}/${CUDA}/repo.html
 
 
 
7
  uv pip install -e .[test]
8
  uv pip install -e .[mace]
 
1
+ TORCH=2.4
2
+ CUDA=cu124
3
  uv pip install torch==${TORCH}.0
4
+ uv pip install torch-scatter torch-sparse -f https://data.pyg.org/whl/torch-${TORCH}.0+${CUDA}.html
 
5
  uv pip install dgl -f https://data.dgl.ai/wheels/torch-${TORCH}/${CUDA}/repo.html
6
+ uv pip install -e .[fairchem]
7
+ uv pip install -e .[orb]
8
+ uv pip install -e .[matgl]
9
  uv pip install -e .[test]
10
  uv pip install -e .[mace]
serve/tasks/homonuclear-diatomics.py CHANGED
@@ -5,10 +5,10 @@ import pandas as pd
5
  import plotly.colors as pcolors
6
  import plotly.graph_objects as go
7
  import streamlit as st
8
- from mlip_arena.models import REGISTRY
9
  from plotly.subplots import make_subplots
10
 
11
- from ase.data import chemical_symbols
12
 
13
  st.markdown(
14
  """
@@ -29,16 +29,7 @@ valid_models = [
29
  mlip_methods = container.multiselect(
30
  "MLIPs",
31
  valid_models,
32
- [
33
- "MACE-MP(M)",
34
- "CHGNet",
35
- "M3GNet",
36
- "MatterSim",
37
- "SevenNet",
38
- "ORBv2",
39
- "eqV2(OMat)",
40
- "ANI2x",
41
- ],
42
  )
43
  dft_methods = container.multiselect("DFT Methods", ["PBE"], ["PBE"])
44
 
 
5
  import plotly.colors as pcolors
6
  import plotly.graph_objects as go
7
  import streamlit as st
8
+ from ase.data import chemical_symbols
9
  from plotly.subplots import make_subplots
10
 
11
+ from mlip_arena.models import REGISTRY
12
 
13
  st.markdown(
14
  """
 
29
  mlip_methods = container.multiselect(
30
  "MLIPs",
31
  valid_models,
32
+ ["MACE-MP(M)", "MatterSim", "SevenNet", "ORBv2", "eqV2(OMat)", "ANI2x", "eSEN"],
 
 
 
 
 
 
 
 
 
33
  )
34
  dft_methods = container.multiselect("DFT Methods", ["PBE"], ["PBE"])
35