ase-calculator-kit 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ase_calculator_kit-0.3.2/LICENSE +21 -0
- ase_calculator_kit-0.3.2/PKG-INFO +502 -0
- ase_calculator_kit-0.3.2/README.md +451 -0
- ase_calculator_kit-0.3.2/pyproject.toml +75 -0
- ase_calculator_kit-0.3.2/setup.cfg +4 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/__init__.py +50 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/__init__.py +24 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/base.py +25 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/dft/__init__.py +11 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/dft/espresso.py +56 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/dft/vasp.py +46 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/mlip/__init__.py +17 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/mlip/chgnet.py +73 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/mlip/fairchem.py +95 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/mlip/mattersim.py +86 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/mlip/nequip.py +110 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/backends/mlip/sevennet.py +153 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/config.py +98 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/device.py +63 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/dispersion.py +193 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/errors.py +39 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/factory.py +113 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/py.typed +0 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit/registry.py +37 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit.egg-info/PKG-INFO +502 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit.egg-info/SOURCES.txt +39 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit.egg-info/dependency_links.txt +1 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit.egg-info/requires.txt +33 -0
- ase_calculator_kit-0.3.2/src/ase_calculator_kit.egg-info/top_level.txt +1 -0
- ase_calculator_kit-0.3.2/tests/test_config.py +96 -0
- ase_calculator_kit-0.3.2/tests/test_device.py +66 -0
- ase_calculator_kit-0.3.2/tests/test_dft_backends.py +114 -0
- ase_calculator_kit-0.3.2/tests/test_dft_factory.py +47 -0
- ase_calculator_kit-0.3.2/tests/test_dispersion.py +136 -0
- ase_calculator_kit-0.3.2/tests/test_factory.py +99 -0
- ase_calculator_kit-0.3.2/tests/test_fairchem_backend.py +14 -0
- ase_calculator_kit-0.3.2/tests/test_mattersim_backend.py +28 -0
- ase_calculator_kit-0.3.2/tests/test_nequip_backend.py +85 -0
- ase_calculator_kit-0.3.2/tests/test_packaging.py +68 -0
- ase_calculator_kit-0.3.2/tests/test_sevennet_backend.py +76 -0
- ase_calculator_kit-0.3.2/tests/test_singlepoint_cpu.py +127 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ishikawa-group
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ase-calculator-kit
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
Summary: Unified ASE calculator factory for MLIP and DFT calculators.
|
|
5
|
+
Author: ishikawa-group
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ishikawa-group/ase-calculator-kit
|
|
8
|
+
Project-URL: Repository, https://github.com/ishikawa-group/ase-calculator-kit
|
|
9
|
+
Project-URL: Changelog, https://github.com/ishikawa-group/ase-calculator-kit/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Issues, https://github.com/ishikawa-group/ase-calculator-kit/issues
|
|
11
|
+
Keywords: ase,calculator,dft,machine-learning,interatomic-potential,mlip,chemistry,materials
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Intended Audience :: Science/Research
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: ase<4,>=3.28
|
|
26
|
+
Requires-Dist: pyyaml<7,>=6.0
|
|
27
|
+
Provides-Extra: chgnet
|
|
28
|
+
Requires-Dist: chgnet<0.5,>=0.4; extra == "chgnet"
|
|
29
|
+
Provides-Extra: sevennet
|
|
30
|
+
Requires-Dist: sevenn<0.13,>=0.12; extra == "sevennet"
|
|
31
|
+
Provides-Extra: mattersim
|
|
32
|
+
Requires-Dist: mattersim<2,>=1.2; extra == "mattersim"
|
|
33
|
+
Provides-Extra: nequip
|
|
34
|
+
Requires-Dist: nequip<0.19,>=0.18; extra == "nequip"
|
|
35
|
+
Provides-Extra: uma
|
|
36
|
+
Requires-Dist: fairchem-core<3,>=2.20; extra == "uma"
|
|
37
|
+
Provides-Extra: dispersion
|
|
38
|
+
Requires-Dist: torch-dftd<0.6,>=0.5; extra == "dispersion"
|
|
39
|
+
Provides-Extra: all
|
|
40
|
+
Requires-Dist: chgnet<0.5,>=0.4; extra == "all"
|
|
41
|
+
Requires-Dist: sevenn<0.13,>=0.12; extra == "all"
|
|
42
|
+
Requires-Dist: mattersim<2,>=1.2; extra == "all"
|
|
43
|
+
Requires-Dist: nequip<0.19,>=0.18; extra == "all"
|
|
44
|
+
Requires-Dist: fairchem-core<3,>=2.20; extra == "all"
|
|
45
|
+
Requires-Dist: torch-dftd<0.6,>=0.5; extra == "all"
|
|
46
|
+
Provides-Extra: dev
|
|
47
|
+
Requires-Dist: pytest==9.0.3; extra == "dev"
|
|
48
|
+
Requires-Dist: ruff==0.15.15; extra == "dev"
|
|
49
|
+
Requires-Dist: tqdm==4.67.3; extra == "dev"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# ase-calculator-kit
|
|
53
|
+
|
|
54
|
+
A thin, unified [ASE](https://wiki.fysik.dtu.dk/ase/) calculator factory for
|
|
55
|
+
machine-learning interatomic potentials and external DFT calculators. Every call
|
|
56
|
+
returns a standard `ase.Calculator`, so the rest of your ASE workflow stays
|
|
57
|
+
unchanged.
|
|
58
|
+
|
|
59
|
+
Supported MLIP backends:
|
|
60
|
+
|
|
61
|
+
- [SevenNet](https://github.com/MDIL-SNU/SevenNet) (installed by default)
|
|
62
|
+
- [CHGNet](https://github.com/CederGroupHub/chgnet)
|
|
63
|
+
- [MatterSim](https://github.com/microsoft/mattersim)
|
|
64
|
+
- [NequIP OAM](https://www.nequip.net/)
|
|
65
|
+
- [UMA / fairchem](https://github.com/facebookresearch/fairchem)
|
|
66
|
+
|
|
67
|
+
Supported DFT backends:
|
|
68
|
+
|
|
69
|
+
- VASP
|
|
70
|
+
- Quantum ESPRESSO (`qe`, `espresso`, `quantum-espresso`)
|
|
71
|
+
|
|
72
|
+
## Install
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install ase-calculator-kit
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The default installation is intentionally lightweight: it pulls in ASE and
|
|
79
|
+
PyYAML and **no NNP backend**, so it does not drag in torch. Each backend is an
|
|
80
|
+
explicit extra — install only what your workflow needs:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# One backend
|
|
84
|
+
pip install "ase-calculator-kit[sevennet]"
|
|
85
|
+
pip install "ase-calculator-kit[chgnet]"
|
|
86
|
+
pip install "ase-calculator-kit[mattersim]"
|
|
87
|
+
pip install "ase-calculator-kit[nequip]"
|
|
88
|
+
pip install "ase-calculator-kit[uma]"
|
|
89
|
+
|
|
90
|
+
# Several selected backends
|
|
91
|
+
pip install "ase-calculator-kit[chgnet,mattersim]"
|
|
92
|
+
|
|
93
|
+
# Every supported NNP backend and the optional D3 correction
|
|
94
|
+
pip install "ase-calculator-kit[all]"
|
|
95
|
+
|
|
96
|
+
# D3 correction without installing every NNP backend
|
|
97
|
+
pip install "ase-calculator-kit[dispersion]"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Missing backend packages are reported only when that calculator is requested,
|
|
101
|
+
with the matching extra to install.
|
|
102
|
+
|
|
103
|
+
### Python versions
|
|
104
|
+
|
|
105
|
+
Python 3.12 and newer. The package itself has no upper bound, but one backend
|
|
106
|
+
currently does:
|
|
107
|
+
|
|
108
|
+
| | 3.12 | 3.13 | 3.14 |
|
|
109
|
+
|---|:--:|:--:|:--:|
|
|
110
|
+
| Core, `chgnet`, `sevennet`, `mattersim`, `nequip`, `dispersion` | ✅ | ✅ | ✅ |
|
|
111
|
+
| `uma` (and therefore `all`) | ✅ | ✅ | ❌ |
|
|
112
|
+
|
|
113
|
+
`fairchem-core` declares `requires-python = ">=3.11,<3.14"` and pins
|
|
114
|
+
`torch~=2.8.0`, which has no cp314 wheels, so `pip install
|
|
115
|
+
"ase-calculator-kit[uma]"` fails on Python 3.14 with an error naming
|
|
116
|
+
`fairchem-core`. Nothing here needs to change once fairchem-core supports 3.14.
|
|
117
|
+
|
|
118
|
+
This is deliberately *not* hidden behind an environment marker: a marker would
|
|
119
|
+
make the install succeed on 3.14 while silently leaving UMA out.
|
|
120
|
+
|
|
121
|
+
Use this import for new code:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from ase_calculator_kit import get_calculator
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Usage
|
|
128
|
+
|
|
129
|
+
MLIP calculators keep the lightweight keyword API:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from ase.build import bulk
|
|
133
|
+
from ase_calculator_kit import get_calculator
|
|
134
|
+
|
|
135
|
+
atoms = bulk("Cu", "fcc", a=3.6)
|
|
136
|
+
|
|
137
|
+
atoms.calc = get_calculator("sevennet", model="7net-omni", modal="mpa")
|
|
138
|
+
print(atoms.get_potential_energy())
|
|
139
|
+
|
|
140
|
+
atoms.calc = get_calculator("chgnet", device="mps")
|
|
141
|
+
print(atoms.get_potential_energy())
|
|
142
|
+
|
|
143
|
+
atoms.calc = get_calculator("mattersim", model="5M")
|
|
144
|
+
print(atoms.get_potential_energy())
|
|
145
|
+
|
|
146
|
+
atoms.calc = get_calculator("nequip", model="L")
|
|
147
|
+
print(atoms.get_potential_energy())
|
|
148
|
+
|
|
149
|
+
atoms.calc = get_calculator("uma", model="uma-s-1p2", task="omat")
|
|
150
|
+
print(atoms.get_potential_energy())
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
DFT calculators are config-only:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
from ase_calculator_kit import get_calculator
|
|
157
|
+
|
|
158
|
+
atoms.calc = get_calculator("vasp", config="examples/dft/vasp_pbe_static.yaml")
|
|
159
|
+
atoms.calc = get_calculator("qe", config="examples/dft/qe_pbe_static.yaml")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
For VASP and QE, arbitrary keyword arguments are intentionally rejected to keep
|
|
163
|
+
calculation conditions explicit and reproducible:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
get_calculator("vasp", encut=520) # TypeError
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
For reproducibility, VASP configs must explicitly specify `profile.command`
|
|
170
|
+
(QE additionally requires `profile.pseudo_dir` and `pseudopotentials`);
|
|
171
|
+
environment-variable-only execution is intentionally not used by this wrapper.
|
|
172
|
+
|
|
173
|
+
Use `overrides=` for small dynamic changes:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
atoms.calc = get_calculator(
|
|
177
|
+
"vasp",
|
|
178
|
+
config="examples/dft/vasp_pbe_static.yaml",
|
|
179
|
+
overrides={"directory": "runs/vasp/Cu_001"},
|
|
180
|
+
)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Write the final merged config for auditability:
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
atoms.calc = get_calculator(
|
|
187
|
+
"qe",
|
|
188
|
+
config="examples/dft/qe_pbe_static.yaml",
|
|
189
|
+
overrides={"directory": "runs/qe/Cu_001"},
|
|
190
|
+
write_resolved_config=True,
|
|
191
|
+
)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## API Reference
|
|
195
|
+
|
|
196
|
+
### Calculator names
|
|
197
|
+
|
|
198
|
+
`get_calculator(name, **kwargs)` takes one of these names (case-insensitive);
|
|
199
|
+
`available_calculators()` returns the same list at runtime.
|
|
200
|
+
|
|
201
|
+
| `name` | Kind | Aliases |
|
|
202
|
+
|---|---|---|
|
|
203
|
+
| `sevennet` | MLIP | — |
|
|
204
|
+
| `chgnet` | MLIP | — |
|
|
205
|
+
| `mattersim` | MLIP | — |
|
|
206
|
+
| `nequip` | MLIP | — |
|
|
207
|
+
| `uma` | MLIP | `fairchem` |
|
|
208
|
+
| `vasp` | DFT | — |
|
|
209
|
+
| `qe` | DFT | `espresso`, `quantum-espresso` |
|
|
210
|
+
|
|
211
|
+
An unknown name raises `ValueError` listing the valid names.
|
|
212
|
+
|
|
213
|
+
### MLIP keyword arguments
|
|
214
|
+
|
|
215
|
+
All MLIP backends accept `device=` (`"auto"` by default; see
|
|
216
|
+
[Apple Silicon (MPS) support](#apple-silicon-mps-support)), `dispersion=False`,
|
|
217
|
+
`dispersion_xc=None`, and forward any extra keywords to the underlying
|
|
218
|
+
calculator.
|
|
219
|
+
|
|
220
|
+
| `name` | Backend-specific keywords (defaults) |
|
|
221
|
+
|---|---|
|
|
222
|
+
| `sevennet` | `model="7net-omni"`, `modal="mpa"`, `enable_cueq=False`, `enable_flash=False` |
|
|
223
|
+
| `chgnet` | `model=None` (bundled default), `checkpoint=None` (path to a `.pth`) |
|
|
224
|
+
| `mattersim` | `model="1M"` (or `"5M"`), `load_path=None` |
|
|
225
|
+
| `nequip` | `model="L"` (`S`/`M`/`L`/`XL`), `model_path=None`, `compile_mode="eager"`, `neighborlist_backend="matscipy"`, `allow_tf32=False` |
|
|
226
|
+
| `uma` | `model="uma-s-1p2"`, `task="omat"` |
|
|
227
|
+
|
|
228
|
+
### DFT keyword arguments
|
|
229
|
+
|
|
230
|
+
DFT backends accept **only** these three; anything else raises `TypeError`.
|
|
231
|
+
|
|
232
|
+
| Keyword | Default | Meaning |
|
|
233
|
+
|---|---|---|
|
|
234
|
+
| `config` | *required* | YAML path or `dict` of calculation conditions |
|
|
235
|
+
| `overrides` | `None` | `dict` deep-merged over `config` |
|
|
236
|
+
| `write_resolved_config` | `False` | Write the merged config into the run directory |
|
|
237
|
+
|
|
238
|
+
### Public helpers
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
from ase_calculator_kit import (
|
|
242
|
+
attach_calculator,
|
|
243
|
+
available_calculators,
|
|
244
|
+
available_dft_calculators,
|
|
245
|
+
available_mlip_models,
|
|
246
|
+
available_models,
|
|
247
|
+
get_dft_calculator,
|
|
248
|
+
get_mlip_calculator,
|
|
249
|
+
resolve_calculator_config,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
available_mlip_models() # ['chgnet', 'fairchem', 'mattersim', 'nequip', 'sevennet', 'uma']
|
|
253
|
+
available_dft_calculators() # ['espresso', 'qe', 'quantum-espresso', 'vasp']
|
|
254
|
+
available_calculators() # both of the above; available_models() is an alias
|
|
255
|
+
attach_calculator(atoms, "uma", task="omat") # sets atoms.calc, returns atoms
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Exceptions
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
from ase_calculator_kit import CalculatorKitError, DispersionError, MissingDependencyError
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
| Exception | Also a | Raised when |
|
|
265
|
+
|---|---|---|
|
|
266
|
+
| `CalculatorKitError` | `Exception` | Base class for everything below |
|
|
267
|
+
| `MissingDependencyError` | `ImportError` | The backend package is not installed; the message names the extra to install |
|
|
268
|
+
| `DispersionError` | `ValueError` | `dispersion=True` is not allowed for that model (see [Dispersion](#dispersion)) |
|
|
269
|
+
| `ValueError` | — | Unknown calculator name, unsupported `device`, or an incomplete DFT config |
|
|
270
|
+
| `TypeError` | — | A DFT backend was given a keyword other than the three above, or `config=` was omitted |
|
|
271
|
+
|
|
272
|
+
## Examples
|
|
273
|
+
|
|
274
|
+
Run a CPU single point with every MLIP model/variant:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
python examples/run_all_models.py
|
|
278
|
+
python examples/run_all_models.py --device auto
|
|
279
|
+
python examples/run_all_models.py --only chgnet sevennet nequip
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Create DFT calculator objects from YAML without running VASP/QE:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
python examples/dft/create_dft_calculator_from_config.py vasp \
|
|
286
|
+
examples/dft/vasp_pbe_static.yaml
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
DFT YAML examples live in [`examples/dft`](examples/dft).
|
|
290
|
+
|
|
291
|
+
## Apple Silicon (MPS) support
|
|
292
|
+
|
|
293
|
+
Every MLIP backend was run on a single point (`bulk("Cu")`) with `device="mps"`
|
|
294
|
+
on an Apple Silicon Mac (arm64, PyTorch 2.8, MPS available). Results:
|
|
295
|
+
|
|
296
|
+
| Backend | `device="mps"` | Notes |
|
|
297
|
+
|---|---|---|
|
|
298
|
+
| SevenNet | ✅ supported | validated locally (`7net-omni`) |
|
|
299
|
+
| CHGNet | ✅ supported | validated locally |
|
|
300
|
+
| MatterSim | ✅ supported | validated locally |
|
|
301
|
+
| NequIP OAM | ❌ not supported | PyTorch MPS lacks float64; the packaged OAM models use float64 buffers |
|
|
302
|
+
| UMA / fairchem | ❌ not supported | `fairchem-core` asserts `device in {"cpu", "cuda"}` |
|
|
303
|
+
|
|
304
|
+
For the MPS-supported backends, `device="auto"` resolves to `mps` on Apple
|
|
305
|
+
Silicon when no CUDA device is present. NequIP and UMA accept only `"cpu"` /
|
|
306
|
+
`"cuda"`; passing `device="mps"` raises a clear `ValueError`, and `device="auto"`
|
|
307
|
+
falls back to `cpu`.
|
|
308
|
+
|
|
309
|
+
## Choosing an MLIP Variant
|
|
310
|
+
|
|
311
|
+
### SevenNet `modal`
|
|
312
|
+
|
|
313
|
+
| `modal` | Use for | Reference level |
|
|
314
|
+
|---|---|---|
|
|
315
|
+
| `mpa` (default) | General-purpose, including molecules | PBE(+U) |
|
|
316
|
+
| `omat24` | Broad / high-force configurations | PBE(+U) |
|
|
317
|
+
| `matpes_pbe` | PBE without Hubbard U | PBE |
|
|
318
|
+
| `matpes_r2scan` | r2SCAN-level materials | r2SCAN |
|
|
319
|
+
| `mp_r2scan` | r2SCAN-level Materials Project data | r2SCAN |
|
|
320
|
+
| `oc20` | Catalyst surfaces and adsorption | RPBE |
|
|
321
|
+
| `oc22` | Oxide catalysis | PBE(+U) |
|
|
322
|
+
| `odac23` | MOFs / direct air capture | PBE-D3 |
|
|
323
|
+
| `omol25_low` | **Low-spin** molecular systems | ωB97M-V |
|
|
324
|
+
| `omol25_high` | **High-spin** molecular systems only | ωB97M-V |
|
|
325
|
+
| `spice` | Drug-like molecules and peptides | ωB97M-D3(BJ) |
|
|
326
|
+
| `qcml` | Small molecules, wide element coverage | PBE0 + MBD-NL |
|
|
327
|
+
| `pet_mad` | PBEsol-level data | PBEsol |
|
|
328
|
+
|
|
329
|
+
`omol25_low` and `omol25_high` split OMol25 by **spin state**, not by accuracy —
|
|
330
|
+
pick the one matching your system. SevenNet's own guidance is that `mpa` stays
|
|
331
|
+
the recommended default even for molecules, organic crystals, and molecular
|
|
332
|
+
liquids; choose another task only when you need consistency with a specific
|
|
333
|
+
functional or benchmark protocol.
|
|
334
|
+
|
|
335
|
+
Single-fidelity models such as `7net-0` do not take `modal`; pass `modal=None`.
|
|
336
|
+
|
|
337
|
+
### NequIP OAM `model`
|
|
338
|
+
|
|
339
|
+
| `model` | Use for |
|
|
340
|
+
|---|---|
|
|
341
|
+
| `S` | Smallest OAM model for quick checks |
|
|
342
|
+
| `M` | Medium OAM model |
|
|
343
|
+
| `L` (default) | Recommended general OAM model for inorganic solids |
|
|
344
|
+
| `XL` | Largest OAM model when higher capacity is worth the cost |
|
|
345
|
+
|
|
346
|
+
NequIP OAM models are loaded through NequIP's `nequip.net:` loader and cached by
|
|
347
|
+
NequIP. To avoid a download, pass `model_path="path/to/model.nequip.zip"`.
|
|
348
|
+
|
|
349
|
+
### MatterSim `model`
|
|
350
|
+
|
|
351
|
+
`1M` (default) is for fast screening, `5M` is more accurate. Keep the checkpoint
|
|
352
|
+
fixed across a campaign.
|
|
353
|
+
|
|
354
|
+
### UMA `task`
|
|
355
|
+
|
|
356
|
+
| `task` | Use for |
|
|
357
|
+
|---|---|
|
|
358
|
+
| `omat` (default) | Inorganic bulk/materials, stress, cell optimization |
|
|
359
|
+
| `omol` | Molecules and polymers |
|
|
360
|
+
| `oc20` | Catalyst surfaces and adsorption |
|
|
361
|
+
| `oc22` | Oxide catalysis |
|
|
362
|
+
| `oc25` | Electrochemistry / solid-liquid interfaces |
|
|
363
|
+
| `odac` | MOFs and direct air capture |
|
|
364
|
+
| `omc` | Molecular crystals |
|
|
365
|
+
|
|
366
|
+
For the molecular task (`omol`), set `atoms.info["charge"]` and
|
|
367
|
+
`atoms.info["spin"]` before computing — see
|
|
368
|
+
[Molecular systems](#molecular-systems-charge-and-spin) for why this matters.
|
|
369
|
+
|
|
370
|
+
## Molecular systems (charge and spin)
|
|
371
|
+
|
|
372
|
+
Molecular models need two inputs that no bulk model does: the **total charge**
|
|
373
|
+
of the system and its **spin multiplicity** (`2S+1`). ASE has no standard place
|
|
374
|
+
for either, so they are passed through `atoms.info`, and the backends differ in
|
|
375
|
+
whether they read them at all.
|
|
376
|
+
|
|
377
|
+
| Backend | Molecular option | Takes charge / spin? |
|
|
378
|
+
|---|---|---|
|
|
379
|
+
| `uma` | `task="omol"` | ✅ `atoms.info["charge"]`, `atoms.info["spin"]` |
|
|
380
|
+
| `sevennet` | `modal="omol25_low"` / `"omol25_high"` / `"spice"` / `"qcml"` | ❌ not supported by sevenn |
|
|
381
|
+
|
|
382
|
+
### UMA: set both keys explicitly
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
from ase.build import molecule
|
|
386
|
+
from ase_calculator_kit import get_calculator
|
|
387
|
+
|
|
388
|
+
atoms = molecule("H2O")
|
|
389
|
+
atoms.info["charge"] = 0 # total charge
|
|
390
|
+
atoms.info["spin"] = 1 # spin multiplicity, 2S+1 (1 = closed shell)
|
|
391
|
+
atoms.calc = get_calculator("uma", task="omol")
|
|
392
|
+
print(atoms.get_potential_energy())
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
A hydroxide anion and a neutral radical are the cases that actually bite:
|
|
396
|
+
|
|
397
|
+
```python
|
|
398
|
+
oh_minus = molecule("OH")
|
|
399
|
+
oh_minus.info["charge"] = -1 # anion
|
|
400
|
+
oh_minus.info["spin"] = 1 # closed shell
|
|
401
|
+
oh_minus.calc = get_calculator("uma", task="omol")
|
|
402
|
+
|
|
403
|
+
oh_radical = molecule("OH")
|
|
404
|
+
oh_radical.info["charge"] = 0
|
|
405
|
+
oh_radical.info["spin"] = 2 # doublet — one unpaired electron
|
|
406
|
+
oh_radical.calc = get_calculator("uma", task="omol")
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
> **Do not rely on the defaults.** fairchem does *not* raise when `charge` or
|
|
410
|
+
> `spin` is missing. It logs a warning, writes `charge=0` / `spin=1` into the
|
|
411
|
+
> `atoms.info` dict you passed in, and returns a neutral closed-shell result.
|
|
412
|
+
> An ion or an open-shell species then comes back **silently wrong**. Set both
|
|
413
|
+
> keys on every molecular structure, including the ones you think are obvious.
|
|
414
|
+
|
|
415
|
+
Both keys are integers. `charge` may range from -100 to 100 and `spin` from 0 to
|
|
416
|
+
100; they are read only by the `omol` head, and other UMA tasks ignore them.
|
|
417
|
+
|
|
418
|
+
### SevenNet: no charge or spin input
|
|
419
|
+
|
|
420
|
+
sevenn has no charge or spin argument, so the `modal` embedding is the only
|
|
421
|
+
handle on the molecular reference data. Charged species and a chosen open-shell
|
|
422
|
+
state **cannot be expressed** — `omol25_high` selects a model trained on
|
|
423
|
+
high-spin configurations, but it is not a multiplicity you set per structure.
|
|
424
|
+
Use `get_calculator("uma", task="omol")` when the charge and spin of the system
|
|
425
|
+
matter.
|
|
426
|
+
|
|
427
|
+
### Non-periodic cells
|
|
428
|
+
|
|
429
|
+
`ase.build.molecule()` returns `pbc=False` with a zero cell, which UMA accepts.
|
|
430
|
+
UMA rejects only two ambiguous cases: a fully periodic structure whose cell is
|
|
431
|
+
all zeros, and a partially periodic one (`pbc=[True, True, False]`).
|
|
432
|
+
|
|
433
|
+
## Dispersion
|
|
434
|
+
|
|
435
|
+
Add a Grimme-D3(BJ) correction on top of MLIP models with `dispersion=True`:
|
|
436
|
+
|
|
437
|
+
```python
|
|
438
|
+
atoms.calc = get_calculator("uma", task="omat", dispersion=True)
|
|
439
|
+
atoms.calc = get_calculator("uma", task="oc20", dispersion=True)
|
|
440
|
+
atoms.calc = get_calculator("chgnet", dispersion=True)
|
|
441
|
+
atoms.calc = get_calculator("sevennet", modal="pet_mad", dispersion=True)
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
With `dispersion=True` the returned object is an ASE
|
|
445
|
+
`SumCalculator([backend_calculator, d3_calculator])`, not the backend calculator
|
|
446
|
+
itself — it satisfies the same `ase.Calculator` interface, but do not rely on
|
|
447
|
+
backend-specific attributes or `isinstance` checks against the backend class.
|
|
448
|
+
|
|
449
|
+
Some models already include dispersion in their training functional, so
|
|
450
|
+
`dispersion=True` is refused for them with `DispersionError`:
|
|
451
|
+
|
|
452
|
+
```python
|
|
453
|
+
get_calculator("uma", task="omol", dispersion=True) # DispersionError: ωB97M-V includes VV10
|
|
454
|
+
get_calculator("sevennet", modal="spice", dispersion=True) # DispersionError: SPICE is ωB97M-D3(BJ)
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**Every molecular task falls in this category** — molecular reference data is
|
|
458
|
+
almost always dispersion-corrected, each dataset in its own way (VV10, an
|
|
459
|
+
explicit D3(BJ) term, or MBD-NL). That verdict cannot be overridden with
|
|
460
|
+
`dispersion_xc=`; remove `dispersion=True` instead. A task this table does not
|
|
461
|
+
cover yet is refused by default but *can* be unlocked with an explicit
|
|
462
|
+
`dispersion_xc` once you have checked its functional yourself.
|
|
463
|
+
|
|
464
|
+
See [`docs/models.md`](docs/models.md) for the full per-model table.
|
|
465
|
+
|
|
466
|
+
## Why no MACE?
|
|
467
|
+
|
|
468
|
+
MACE is intentionally excluded. `mace-torch` requires an `e3nn` version that
|
|
469
|
+
conflicts with the `e3nn` pinned by SevenNet (`sevenn`) and UMA
|
|
470
|
+
(`fairchem-core`). If you need MACE, use dedicated MACE tooling in a separate
|
|
471
|
+
environment.
|
|
472
|
+
|
|
473
|
+
## Development
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
python -m venv .venv
|
|
477
|
+
.venv/bin/pip install -e ".[dev]" -c constraints.txt
|
|
478
|
+
.venv/bin/pytest
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
`pyproject.toml` declares compatible version ranges so the package installs
|
|
482
|
+
next to whatever ASE/NNP versions you already have; `constraints.txt` pins the
|
|
483
|
+
exact combination that is tested, and CI installs with it.
|
|
484
|
+
|
|
485
|
+
`pytest` runs only the fast tests by default. Slow tests
|
|
486
|
+
(`pytest -m slow`) run real MLIP CPU single-point calculations and may download
|
|
487
|
+
model weights; install `.[dev,all] -c constraints.txt` first so every backend is
|
|
488
|
+
importable.
|
|
489
|
+
|
|
490
|
+
## Further Reading
|
|
491
|
+
|
|
492
|
+
- [`docs/models.md`](docs/models.md) — per-model dispersion policy and training
|
|
493
|
+
functionals.
|
|
494
|
+
- [`docs/code-guide_ja.md`](docs/code-guide_ja.md) — 実装の化学的な判断と
|
|
495
|
+
モジュールの責務(日本語).
|
|
496
|
+
- [`AGENTS.md`](AGENTS.md) — repository map, invariants, and conventions for
|
|
497
|
+
AI coding agents (Claude, GPT, and others).
|
|
498
|
+
- [`CHANGELOG.md`](CHANGELOG.md) — release history.
|
|
499
|
+
|
|
500
|
+
## License
|
|
501
|
+
|
|
502
|
+
MIT
|