xnns 0.1.0__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.
- xnns-0.1.0/LICENSE +21 -0
- xnns-0.1.0/PKG-INFO +422 -0
- xnns-0.1.0/README.md +332 -0
- xnns-0.1.0/pyproject.toml +148 -0
- xnns-0.1.0/setup.cfg +4 -0
- xnns-0.1.0/src/xnn/__init__.py +52 -0
- xnns-0.1.0/src/xnn/__main__.py +10 -0
- xnns-0.1.0/src/xnn/cnn/__init__.py +4 -0
- xnns-0.1.0/src/xnn/cnn/models/__init__.py +3 -0
- xnns-0.1.0/src/xnn/cnn/models/schnet.py +472 -0
- xnns-0.1.0/src/xnn/common/__init__.py +11 -0
- xnns-0.1.0/src/xnn/common/_torch_compat.py +39 -0
- xnns-0.1.0/src/xnn/common/benchmark/__init__.py +46 -0
- xnns-0.1.0/src/xnn/common/benchmark/config.py +447 -0
- xnns-0.1.0/src/xnn/common/benchmark/energy.py +184 -0
- xnns-0.1.0/src/xnn/common/benchmark/metrics.py +268 -0
- xnns-0.1.0/src/xnn/common/benchmark/report.py +321 -0
- xnns-0.1.0/src/xnn/common/benchmark/runner.py +311 -0
- xnns-0.1.0/src/xnn/common/cli/__init__.py +3 -0
- xnns-0.1.0/src/xnn/common/cli/main.py +162 -0
- xnns-0.1.0/src/xnn/common/config/__init__.py +11 -0
- xnns-0.1.0/src/xnn/common/config/coerce.py +155 -0
- xnns-0.1.0/src/xnn/common/config/loaders.py +186 -0
- xnns-0.1.0/src/xnn/common/config/schema.py +204 -0
- xnns-0.1.0/src/xnn/common/config/translate.py +197 -0
- xnns-0.1.0/src/xnn/common/data/__init__.py +11 -0
- xnns-0.1.0/src/xnn/common/data/ase_io.py +129 -0
- xnns-0.1.0/src/xnn/common/data/atomic_data.py +173 -0
- xnns-0.1.0/src/xnn/common/data/dataset.py +273 -0
- xnns-0.1.0/src/xnn/common/data/hub/__init__.py +45 -0
- xnns-0.1.0/src/xnn/common/data/hub/_download.py +177 -0
- xnns-0.1.0/src/xnn/common/data/hub/ani1.py +233 -0
- xnns-0.1.0/src/xnn/common/data/hub/ani1ccx.py +106 -0
- xnns-0.1.0/src/xnn/common/data/hub/ani1x.py +224 -0
- xnns-0.1.0/src/xnn/common/data/hub/ani2x.py +233 -0
- xnns-0.1.0/src/xnn/common/data/hub/argon_md.py +108 -0
- xnns-0.1.0/src/xnn/common/data/hub/base.py +176 -0
- xnns-0.1.0/src/xnn/common/data/hub/lode_dimers.py +255 -0
- xnns-0.1.0/src/xnn/common/data/hub/rmd17.py +248 -0
- xnns-0.1.0/src/xnn/common/data/neighborlist.py +227 -0
- xnns-0.1.0/src/xnn/common/deploy/__init__.py +16 -0
- xnns-0.1.0/src/xnn/common/deploy/ase_calculator.py +126 -0
- xnns-0.1.0/src/xnn/common/deploy/lammps.py +166 -0
- xnns-0.1.0/src/xnn/common/deploy/mdi_engine.py +446 -0
- xnns-0.1.0/src/xnn/common/deploy/torchscript.py +558 -0
- xnns-0.1.0/src/xnn/common/featurizers/__init__.py +6 -0
- xnns-0.1.0/src/xnn/common/featurizers/base.py +75 -0
- xnns-0.1.0/src/xnn/common/featurizers/cutoff.py +41 -0
- xnns-0.1.0/src/xnn/common/featurizers/radial.py +59 -0
- xnns-0.1.0/src/xnn/common/models/__init__.py +17 -0
- xnns-0.1.0/src/xnn/common/models/base.py +112 -0
- xnns-0.1.0/src/xnn/common/models/les.py +384 -0
- xnns-0.1.0/src/xnn/common/models/ops.py +135 -0
- xnns-0.1.0/src/xnn/common/models/outputs.py +148 -0
- xnns-0.1.0/src/xnn/common/models/registry.py +120 -0
- xnns-0.1.0/src/xnn/common/train/__init__.py +4 -0
- xnns-0.1.0/src/xnn/common/train/losses.py +76 -0
- xnns-0.1.0/src/xnn/common/train/trainer.py +450 -0
- xnns-0.1.0/src/xnn/dnn/__init__.py +4 -0
- xnns-0.1.0/src/xnn/dnn/featurizers/__init__.py +6 -0
- xnns-0.1.0/src/xnn/dnn/featurizers/aev.py +221 -0
- xnns-0.1.0/src/xnn/dnn/featurizers/symmetry_functions.py +251 -0
- xnns-0.1.0/src/xnn/dnn/models/__init__.py +6 -0
- xnns-0.1.0/src/xnn/dnn/models/ani.py +353 -0
- xnns-0.1.0/src/xnn/dnn/models/base.py +224 -0
- xnns-0.1.0/src/xnn/dnn/models/d3.py +236 -0
- xnns-0.1.0/src/xnn/dnn/models/d3_tables.npz +0 -0
- xnns-0.1.0/src/xnn/dnn/models/hdnnp.py +68 -0
- xnns-0.1.0/src/xnn/dnn/models/physnet.py +615 -0
- xnns-0.1.0/src/xnn/ffnn/__init__.py +25 -0
- xnns-0.1.0/src/xnn/ffnn/common/__init__.py +29 -0
- xnns-0.1.0/src/xnn/ffnn/common/elements.py +37 -0
- xnns-0.1.0/src/xnn/ffnn/common/frc.py +1583 -0
- xnns-0.1.0/src/xnn/ffnn/common/typing.py +237 -0
- xnns-0.1.0/src/xnn/ffnn/data/LICENSE-SEAMM +29 -0
- xnns-0.1.0/src/xnn/ffnn/data/README.md +65 -0
- xnns-0.1.0/src/xnn/ffnn/data/lopls.frc +161 -0
- xnns-0.1.0/src/xnn/ffnn/data/oplsaa.frc +11726 -0
- xnns-0.1.0/src/xnn/ffnn/data/oplsaa_1996.frc +57 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CHLiOFSi_Yun_2017.frc +322 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CHNOFSClNiPt_FC_2013.frc +461 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CHNO_HNS_2014.frc +272 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CHNO_RDX_2003.frc +270 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CHOFe_FeOH_2010.frc +265 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CHOV_VOH_2008.frc +270 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CHO_cho_2008.frc +227 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CH_2018.frc +162 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/CLiSi_Guifo_2023.frc +185 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/HBNO_AB_2010.frc +253 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/HOAu_AuO_2010.frc +223 -0
- xnns-0.1.0/src/xnn/ffnn/data/reaxff/HOZn_ZNOH_2010.frc +199 -0
- xnns-0.1.0/src/xnn/ffnn/models/__init__.py +11 -0
- xnns-0.1.0/src/xnn/ffnn/models/ffield.py +1093 -0
- xnns-0.1.0/src/xnn/ffnn/models/opls.py +980 -0
- xnns-0.1.0/src/xnn/ffnn/models/oplslib.py +632 -0
- xnns-0.1.0/src/xnn/ffnn/models/reaxff.py +1729 -0
- xnns-0.1.0/src/xnn/ffnn/models/topology.py +403 -0
- xnns-0.1.0/src/xnn/gnn/__init__.py +4 -0
- xnns-0.1.0/src/xnn/gnn/featurizers/__init__.py +7 -0
- xnns-0.1.0/src/xnn/gnn/featurizers/cartesian.py +152 -0
- xnns-0.1.0/src/xnn/gnn/featurizers/cutoff.py +52 -0
- xnns-0.1.0/src/xnn/gnn/featurizers/radial.py +71 -0
- xnns-0.1.0/src/xnn/gnn/featurizers/spherical.py +173 -0
- xnns-0.1.0/src/xnn/gnn/models/__init__.py +7 -0
- xnns-0.1.0/src/xnn/gnn/models/allegro.py +601 -0
- xnns-0.1.0/src/xnn/gnn/models/base.py +168 -0
- xnns-0.1.0/src/xnn/gnn/models/blocks.py +209 -0
- xnns-0.1.0/src/xnn/gnn/models/cace.py +685 -0
- xnns-0.1.0/src/xnn/gnn/models/mace.py +1215 -0
- xnns-0.1.0/src/xnn/gnn/models/nequip.py +794 -0
- xnns-0.1.0/src/xnn/hybrid/__init__.py +18 -0
- xnns-0.1.0/src/xnn/hybrid/models/__init__.py +4 -0
- xnns-0.1.0/src/xnn/hybrid/models/bamboo.py +597 -0
- xnns-0.1.0/src/xnn/hybrid/models/dispersion.py +108 -0
- xnns-0.1.0/src/xnn/transformer/__init__.py +18 -0
- xnns-0.1.0/src/xnn/transformer/attention.py +109 -0
- xnns-0.1.0/src/xnn/transformer/featurizers/__init__.py +4 -0
- xnns-0.1.0/src/xnn/transformer/featurizers/radial.py +110 -0
- xnns-0.1.0/src/xnns.egg-info/PKG-INFO +422 -0
- xnns-0.1.0/src/xnns.egg-info/SOURCES.txt +146 -0
- xnns-0.1.0/src/xnns.egg-info/dependency_links.txt +1 -0
- xnns-0.1.0/src/xnns.egg-info/entry_points.txt +2 -0
- xnns-0.1.0/src/xnns.egg-info/requires.txt +74 -0
- xnns-0.1.0/src/xnns.egg-info/top_level.txt +1 -0
- xnns-0.1.0/tests/test_allegro.py +183 -0
- xnns-0.1.0/tests/test_ani.py +404 -0
- xnns-0.1.0/tests/test_ase_io.py +146 -0
- xnns-0.1.0/tests/test_atom_typing.py +155 -0
- xnns-0.1.0/tests/test_bamboo.py +309 -0
- xnns-0.1.0/tests/test_benchmark.py +533 -0
- xnns-0.1.0/tests/test_cace.py +225 -0
- xnns-0.1.0/tests/test_deploy_torchscript.py +298 -0
- xnns-0.1.0/tests/test_frc.py +380 -0
- xnns-0.1.0/tests/test_gnn.py +116 -0
- xnns-0.1.0/tests/test_hub.py +840 -0
- xnns-0.1.0/tests/test_les.py +375 -0
- xnns-0.1.0/tests/test_mace.py +195 -0
- xnns-0.1.0/tests/test_neighborlist.py +113 -0
- xnns-0.1.0/tests/test_neighborlist_backends.py +118 -0
- xnns-0.1.0/tests/test_nequip.py +221 -0
- xnns-0.1.0/tests/test_opls.py +831 -0
- xnns-0.1.0/tests/test_physnet.py +241 -0
- xnns-0.1.0/tests/test_reaxff.py +604 -0
- xnns-0.1.0/tests/test_schnet.py +315 -0
- xnns-0.1.0/tests/test_smoke.py +94 -0
- xnns-0.1.0/tests/test_structure_to_graph_device.py +70 -0
- xnns-0.1.0/tests/test_torch_compat.py +56 -0
- xnns-0.1.0/tests/test_trainer_distributed.py +64 -0
xnns-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MolSSI AI
|
|
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.
|
xnns-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xnns
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Machine-learning interatomic potentials in PyTorch for molecular and periodic systems
|
|
5
|
+
Author-email: Mohammad Mostafanejad <smostafanejad@molssi.org>
|
|
6
|
+
Maintainer-email: MolSSI AI <smostafanejad@molssi.org>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/molssi-ai/xnn
|
|
9
|
+
Project-URL: Documentation, https://molssi-ai.github.io/xnn/
|
|
10
|
+
Project-URL: Source, https://github.com/molssi-ai/xnn
|
|
11
|
+
Project-URL: Issues, https://github.com/molssi-ai/xnn/issues
|
|
12
|
+
Project-URL: Changelog, https://github.com/molssi-ai/xnn/releases
|
|
13
|
+
Keywords: interatomic potentials,machine learning,molecular dynamics,MACE,NequIP,Allegro,SchNet,PhysNet,ANI,ReaxFF,OPLS,pytorch,LAMMPS,ASE
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: torch>=2.0
|
|
29
|
+
Requires-Dist: numpy
|
|
30
|
+
Requires-Dist: pyyaml
|
|
31
|
+
Requires-Dist: tqdm
|
|
32
|
+
Provides-Extra: ase
|
|
33
|
+
Requires-Dist: ase>=3.22; extra == "ase"
|
|
34
|
+
Provides-Extra: hub
|
|
35
|
+
Requires-Dist: h5py>=3.0; extra == "hub"
|
|
36
|
+
Provides-Extra: gnn
|
|
37
|
+
Requires-Dist: e3nn>=0.4.4; extra == "gnn"
|
|
38
|
+
Provides-Extra: mdi
|
|
39
|
+
Requires-Dist: pymdi>=1.4; extra == "mdi"
|
|
40
|
+
Provides-Extra: vesin
|
|
41
|
+
Requires-Dist: vesin-torch>=0.3; extra == "vesin"
|
|
42
|
+
Provides-Extra: hydra
|
|
43
|
+
Requires-Dist: hydra-core>=1.3; extra == "hydra"
|
|
44
|
+
Requires-Dist: omegaconf>=2.3; extra == "hydra"
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: pytest; extra == "dev"
|
|
47
|
+
Provides-Extra: docs
|
|
48
|
+
Requires-Dist: sphinx>=7; extra == "docs"
|
|
49
|
+
Requires-Dist: pydata-sphinx-theme>=0.15; extra == "docs"
|
|
50
|
+
Requires-Dist: sphinx-design; extra == "docs"
|
|
51
|
+
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
52
|
+
Requires-Dist: sphinx-togglebutton; extra == "docs"
|
|
53
|
+
Requires-Dist: myst-nb>=1.1; extra == "docs"
|
|
54
|
+
Provides-Extra: examples
|
|
55
|
+
Requires-Dist: ase>=3.22; extra == "examples"
|
|
56
|
+
Requires-Dist: e3nn>=0.4.4; extra == "examples"
|
|
57
|
+
Requires-Dist: h5py>=3.0; extra == "examples"
|
|
58
|
+
Requires-Dist: mace-torch==0.3.16; extra == "examples"
|
|
59
|
+
Requires-Dist: nequip==0.6.2; extra == "examples"
|
|
60
|
+
Requires-Dist: matplotlib>=3.8; extra == "examples"
|
|
61
|
+
Requires-Dist: jupyter; extra == "examples"
|
|
62
|
+
Requires-Dist: ipykernel; extra == "examples"
|
|
63
|
+
Requires-Dist: nbconvert; extra == "examples"
|
|
64
|
+
Requires-Dist: nbformat; extra == "examples"
|
|
65
|
+
Requires-Dist: openmm>=8.0; extra == "examples"
|
|
66
|
+
Requires-Dist: rdkit>=2023.9; extra == "examples"
|
|
67
|
+
Provides-Extra: ani
|
|
68
|
+
Requires-Dist: torchani==2.2.4; extra == "ani"
|
|
69
|
+
Requires-Dist: h5py>=3.0; extra == "ani"
|
|
70
|
+
Provides-Extra: ffnn
|
|
71
|
+
Requires-Dist: rdkit>=2023.9; extra == "ffnn"
|
|
72
|
+
Provides-Extra: opls
|
|
73
|
+
Requires-Dist: openmm>=8.0; extra == "opls"
|
|
74
|
+
Requires-Dist: rdkit>=2023.9; extra == "opls"
|
|
75
|
+
Provides-Extra: all
|
|
76
|
+
Requires-Dist: ase>=3.22; extra == "all"
|
|
77
|
+
Requires-Dist: e3nn>=0.4.4; extra == "all"
|
|
78
|
+
Requires-Dist: vesin-torch>=0.3; extra == "all"
|
|
79
|
+
Requires-Dist: hydra-core>=1.3; extra == "all"
|
|
80
|
+
Requires-Dist: omegaconf>=2.3; extra == "all"
|
|
81
|
+
Requires-Dist: pytest; extra == "all"
|
|
82
|
+
Requires-Dist: mace-torch==0.3.16; extra == "all"
|
|
83
|
+
Requires-Dist: nequip==0.6.2; extra == "all"
|
|
84
|
+
Requires-Dist: matplotlib>=3.8; extra == "all"
|
|
85
|
+
Requires-Dist: jupyter; extra == "all"
|
|
86
|
+
Requires-Dist: ipykernel; extra == "all"
|
|
87
|
+
Requires-Dist: nbconvert; extra == "all"
|
|
88
|
+
Requires-Dist: nbformat; extra == "all"
|
|
89
|
+
Dynamic: license-file
|
|
90
|
+
|
|
91
|
+
# xnn
|
|
92
|
+
|
|
93
|
+
Machine-learning interatomic potentials for **molecules and materials** behind a
|
|
94
|
+
single coherent PyTorch interface.
|
|
95
|
+
|
|
96
|
+
## Installation
|
|
97
|
+
|
|
98
|
+
From PyPI, where the distribution is called `xnns` (the import name and the
|
|
99
|
+
command line are `xnn`):
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
pip install xnns # core (torch, numpy, pyyaml)
|
|
103
|
+
pip install "xnns[gnn,ase]" # + e3nn for NequIP/MACE/Allegro, + ASE calculator
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
From a clone, for development:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
pip install -e . # core (torch, numpy, pyyaml)
|
|
110
|
+
pip install -e ".[ase]" # + ASE calculator
|
|
111
|
+
pip install -e ".[gnn]" # + e3nn for NequIP/MACE/Allegro
|
|
112
|
+
pip install -e ".[hydra]" # + Hydra/OmegaConf config
|
|
113
|
+
pip install -e ".[examples]" # + ASE, e3nn, mace-torch, nequip, jupyter (runs the notebooks)
|
|
114
|
+
pip install -e ".[all]"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The Allegro reference implementation used by one fidelity notebook is not on
|
|
118
|
+
PyPI; install it separately with
|
|
119
|
+
`pip install "git+https://github.com/mir-group/allegro@v0.3.0"`.
|
|
120
|
+
|
|
121
|
+
## Quick start
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# builds trains a model on toy data and predicts on a test set
|
|
125
|
+
python examples/quickstart.py
|
|
126
|
+
|
|
127
|
+
# smoke tests for all models and families
|
|
128
|
+
pytest tests/
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from xnn.common.config import Config
|
|
133
|
+
from xnn.common.data import AtomicDataset
|
|
134
|
+
from xnn.common.train import Trainer
|
|
135
|
+
|
|
136
|
+
cfg = Config()
|
|
137
|
+
# E.g. schnet | hdnnp | ani | physnet | nequip | mace | allegro | cace | reaxff
|
|
138
|
+
cfg.model.name = "nequip"
|
|
139
|
+
# Unshared model specific hyperparameters go here
|
|
140
|
+
cfg.model.extra = {"species": [1, 6, 8], "l_max": 2}
|
|
141
|
+
# batch_size = 1 disables batch training
|
|
142
|
+
cfg.data.batch_size = 16
|
|
143
|
+
# auto | cpu | cuda | cuda:0
|
|
144
|
+
cfg.device = "auto"
|
|
145
|
+
Trainer(cfg, AtomicDataset(structures, cfg.model.cutoff)).fit()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`structures` is a list of plain dictionaries (`pos`, `atomic_numbers`, and
|
|
149
|
+
optionally, `cell`/`pbc` and `energy`/`forces`/`stress` targets). Data in any
|
|
150
|
+
ASE-native format loads directly and targets can also be included. So, no
|
|
151
|
+
pre-wrapping is required:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
# xnn supports ase-io native formats such as .extxyz, .cif, VASP, ...
|
|
155
|
+
train_set = AtomicDataset.from_file("trajectory.extxyz", cutoff=4.0)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Design principles
|
|
159
|
+
|
|
160
|
+
Four ideas hold `xnn` together:
|
|
161
|
+
|
|
162
|
+
1. **Unified data object.** Every model consumes an `AtomicGraph` and returns
|
|
163
|
+
`{"node_energy", "energy"}`. Molecular vs. periodic is invisible to models:
|
|
164
|
+
periodicity lives only in `edge_vectors()` (`r_ij = pos[dst] - pos[src] +
|
|
165
|
+
cell_shift @ cell`), keeping forces and stress differentiable.
|
|
166
|
+
2. **Featurizers are first-class.** A `Featurizer` (subclass of `nn.Module`)
|
|
167
|
+
turns a graph into invariant descriptors (symmetry functions, AEV) or
|
|
168
|
+
equivariant edge attributes (spherical harmonics, Cartesian monomials).
|
|
169
|
+
Descriptor models (HDNNP, ANI) and GNNs (NequIP/MACE/Allegro/CACE) are thin
|
|
170
|
+
compositions over featurizers, so the featurization is reusable and
|
|
171
|
+
inspectable on its own.
|
|
172
|
+
3. **Forces/stress in one place.** `ForceStressOutput` wraps any model and
|
|
173
|
+
differentiates energy w.r.t. positions (forces) and a symmetric strain
|
|
174
|
+
(stress). Models never implement them. The same wrapper idea powers
|
|
175
|
+
`LatentEwald` (Latent Ewald Summation, Cheng 2025): every model exposes
|
|
176
|
+
invariant `"node_features"`, so long-range electrostatics/dispersion can be
|
|
177
|
+
added to *any* short-range model with `extra: {long_range: {...}}` — a
|
|
178
|
+
faithful port of the CACE-LR reference implementation (see
|
|
179
|
+
`tests/test_les.py` and `examples/gnn/les/`).
|
|
180
|
+
4. **Extensibility via registry + one config, three frontends.**
|
|
181
|
+
`@register_model("name")` + a `from_config` classmethod makes a model usable
|
|
182
|
+
from any of YAML / argparse / Hydra, which all funnel into one
|
|
183
|
+
`Config` dataclass.
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
# Data (structures dict -> AtomicGraph)
|
|
188
|
+
from xnn.common.data import AtomicDataset, build_neighbor_list
|
|
189
|
+
ds = AtomicDataset(structures, cutoff=5.0)
|
|
190
|
+
graph = ds[0]
|
|
191
|
+
|
|
192
|
+
# Featurizers (AtomicGraph -> model inputs)
|
|
193
|
+
from xnn.dnn.featurizers import AEV, RadialSymmetryFunctions
|
|
194
|
+
from xnn.gnn.featurizers import SphericalHarmonicEdgeEmbedding
|
|
195
|
+
# (N, D) invariant per-atom AEV
|
|
196
|
+
descriptor = AEV(species=[1, 6, 8])(graph)
|
|
197
|
+
# Equivariant edge attributes
|
|
198
|
+
edges = SphericalHarmonicEdgeEmbedding(l_max=2)(graph)
|
|
199
|
+
|
|
200
|
+
# Models (model inputs -> energy)
|
|
201
|
+
from xnn.common.models import build_model, ForceStressOutput, available_models
|
|
202
|
+
# Any registered model + autograd forces/stress
|
|
203
|
+
model = ForceStressOutput(build_model(cfg.model))
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Config frontends (interchangeable)
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from xnn.common.config import from_yaml, from_argparse, from_hydra
|
|
210
|
+
cfg = from_yaml("configs/train.yaml")
|
|
211
|
+
cfg = from_argparse(["--config", "configs/train.yaml", "--set", "model.cutoff=6.0"])
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
CLI: `xnn train --config configs/train.yaml --set optim.epochs=50`
|
|
215
|
+
(also `xnn benchmark --config configs/benchmark.yaml` and
|
|
216
|
+
`xnn export --config ... --ckpt ... --to lammps|torchscript`).
|
|
217
|
+
|
|
218
|
+
Model keys copied verbatim from an upstream code's yaml also work: a per-model
|
|
219
|
+
key-translation registry (`xnn.common.config.translate`) rewrites the foreign
|
|
220
|
+
spellings (MACE-CLI `r_max`/`num_radial_basis`/`atomic_numbers`/`E0s`, NequIP
|
|
221
|
+
`num_layers`, ...) to the xnn canonical names at config-load time; the xnn
|
|
222
|
+
spelling wins if both are given. Extend it for another code with
|
|
223
|
+
`register_key_translation("name", {...})`.
|
|
224
|
+
|
|
225
|
+
## Deployment
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from xnn.common.deploy import XNNCalculator, export_to_lammps
|
|
229
|
+
atoms.calc = XNNCalculator(model, cutoff=5.0) # ASE
|
|
230
|
+
export_to_lammps(model, cutoff=5.0, path="deployed.pt") # TorchScript for LAMMPS
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Pair the exported `.pt` with the matching C++ pair style (pair_nequip /
|
|
234
|
+
pair_mace / pair_allegro pattern). The `LAMMPSWrapper` in
|
|
235
|
+
`common/deploy/lammps.py` defines the tensor ABI. A model is exportable when it
|
|
236
|
+
provides the scriptable `node_energy(atomic_numbers, edge_index, edge_vec)`
|
|
237
|
+
core -- SchNet, NequIP, MACE and Allegro all do (the scripted models reproduce
|
|
238
|
+
the eager ones to ~1e-15, verified in `tests/test_schnet.py` /
|
|
239
|
+
`tests/test_mace.py` / `tests/test_nequip.py` / `tests/test_allegro.py`). For NequIP this required a scriptable, bit-exact stand-in
|
|
240
|
+
for e3nn's `Gate` (`xnn.gnn.models.nequip._Gate`), which the e3nn 0.4.4
|
|
241
|
+
original cannot do on torch 2.x.
|
|
242
|
+
|
|
243
|
+
## Benchmarking
|
|
244
|
+
|
|
245
|
+
Score a set of **pre-trained** models on one dataset with
|
|
246
|
+
`xnn.common.benchmark` and tabulate their errors. A single config lists the
|
|
247
|
+
`models` (each an architecture plus the `checkpoint` to load) and the
|
|
248
|
+
`metrics` mapping, which ties each target quantity (`energy` / `forces` /
|
|
249
|
+
`stress`) to the error metrics reported for it (`mae` / `mse` / `rmse`, or
|
|
250
|
+
custom callables). Results are tabulated per model and
|
|
251
|
+
written to CSV / JSON / Markdown (or a user-registered format). Energy can be
|
|
252
|
+
scored per atom or, with `atomic_energies` (a `{Z: E0}` map or `average` to fit
|
|
253
|
+
from data), as the physically meaningful atomization (interaction) energy.
|
|
254
|
+
Benchmarking does not train — produce the checkpoints first with `xnn train`.
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
xnn benchmark --config configs/benchmark.yaml
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
from xnn.common.benchmark import from_yaml, run_benchmark
|
|
262
|
+
rows = run_benchmark(from_yaml("configs/benchmark.yaml"))
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The benchmark builds models with the same `Config` and model registry as a
|
|
266
|
+
single run; new metrics and output formats plug in via `@register_metric` and
|
|
267
|
+
`@register_writer`, mirroring `@register_model`.
|
|
268
|
+
|
|
269
|
+
## Available models
|
|
270
|
+
|
|
271
|
+
| Model | Family | Featurizers | State |
|
|
272
|
+
|---|---|---|---|
|
|
273
|
+
| SchNet | cnn | Gaussian RBF | Under development |
|
|
274
|
+
| PhysNet | dnn | exp-Gaussian rbf + attention masks | Complete: Training, Evaluation, Deployment (ASE only) |
|
|
275
|
+
| HDNNP | dnn | radial symmetry functions (G2) | Under development |
|
|
276
|
+
| ANI | dnn | AEV (radial + angular symmetry functions) | Complete: Training, Evaluation, Deployment (ASE only) |
|
|
277
|
+
| NequIP | gnn | spherical-harmonic edges | Complete: Training, Evaluation, Deployment (TorchScript, LAMMPS, ASE) |
|
|
278
|
+
| MACE | gnn | spherical-harmonic edges | Complete: Training, Evaluation, Deployment (TorchScript, LAMMPS, ASE) |
|
|
279
|
+
| CACE | gnn | Cartesian monomial edges | Complete: Training, Evaluation, Deployment (ASE only) |
|
|
280
|
+
| Allegro | gnn | spherical-harmonic edges | Complete: Training, Evaluation, Deployment (TorchScript, LAMMPS, ASE) |
|
|
281
|
+
| BAMBOO | hybrid | exp-normal rbf + multi-head edge attention | Complete: Training, Evaluation, Deployment (ASE only) |
|
|
282
|
+
| ReaxFF / ReaxFF-nn | ffnn | bond orders + EEM charges (the force field is the model) | Complete: Training, Evaluation, Deployment (ASE only) |
|
|
283
|
+
| OPLS / OPLS-AA / L-OPLS | ffnn | fixed valence topology (the force field is the model) | Complete: Training, Evaluation, Deployment (ASE only) |
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
<details> <!-- Start Package layout -->
|
|
287
|
+
<summary><h2 style="display:inline-block">Package layout</h2></summary>
|
|
288
|
+
|
|
289
|
+
The package is organized **by model family** (`gnn`, `cnn`, `dnn`, `ffnn`, `hybrid`),
|
|
290
|
+
with shared resources factored into the `common` modules and reusable
|
|
291
|
+
transformer building blocks in `transformer`. An object (e.g., function, module
|
|
292
|
+
etc.) lives with the model family that uses it, or with `common` if more than
|
|
293
|
+
one family needs it. Of course, layers are designed as stand-alone entities and
|
|
294
|
+
can be imported on their own.
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
src/xnn/
|
|
298
|
+
├── __main__.py `python -m xnn` entry point
|
|
299
|
+
├── common/ shared across all model families
|
|
300
|
+
│ ├── data/ - common data abstractions
|
|
301
|
+
│ │ └── … + AtomicGraph (the one data object), PBC neighbor list, AtomicDataset, ASE I/O
|
|
302
|
+
│ ├── featurizers/ - common featurizers
|
|
303
|
+
│ │ └── … + Featurizer base + shared basis functions (GaussianRBF, CosineCutoff)
|
|
304
|
+
│ ├── config/ - one dataclass schema; loaders for yaml / argparse / hydra
|
|
305
|
+
│ │ └── … + schema, loaders, translate, coerce
|
|
306
|
+
│ ├── models/ - InteratomicPotential interface, registry, ForceStressOutput, ops (scatter_sum, shifted_softplus)
|
|
307
|
+
│ │ └── … + base, registry, outputs, les, ops
|
|
308
|
+
│ ├── train/ - Trainer (batch + device aware), weighted energy/force/stress loss
|
|
309
|
+
│ │ └── … + trainer, losses
|
|
310
|
+
│ ├── benchmark/ - score pre-trained models on a dataset (metrics, atomization energy, report writers)
|
|
311
|
+
│ │ └── … + config, runner, metrics, energy, report
|
|
312
|
+
│ ├── deploy/ - ASE Calculator, and LAMMPS/TorchScript export
|
|
313
|
+
│ │ └── … + ase_calculator, lammps
|
|
314
|
+
│ └── cli/ - the `xnn` command-line interface
|
|
315
|
+
│ └── main.py
|
|
316
|
+
├── gnn/ graph potentials
|
|
317
|
+
│ ├── featurizers/ - GNN featurizers
|
|
318
|
+
│ │ └── … + spherical, cartesian, radial, cutoff
|
|
319
|
+
│ └── models/ - base (GNNPotential, EquivariantGNN), blocks, nequip, mace, allegro, cace
|
|
320
|
+
│ └── … + base, blocks, nequip, mace, allegro, cace
|
|
321
|
+
├── cnn/ continuous-filter conv net
|
|
322
|
+
│ └── models/ - schnet
|
|
323
|
+
├── dnn/ descriptor + per-element networks, and PhysNet
|
|
324
|
+
│ ├── featurizers/ - DNN featurizers
|
|
325
|
+
│ │ └── … + symmetry functions, AEV
|
|
326
|
+
│ └── models/ base (DescriptorPotential), hdnnp, ani, physnet and ported Grimme's D3
|
|
327
|
+
│ └── …
|
|
328
|
+
├── ffnn/ learnable classical force fields
|
|
329
|
+
│ ├── common/ - frc (SEAMM .frc force-field files: reader, resolver, writer, registry),
|
|
330
|
+
│ │ typing (SMARTS atom typing), elements
|
|
331
|
+
│ ├── data/ - shipped parameter files: oplsaa.frc, lopls.frc, oplsaa_1996.frc, reaxff/*.frc
|
|
332
|
+
│ └── models/ - reaxff, ffield, opls, oplslib, topology
|
|
333
|
+
│ └── … + ReaxFF / ReaxFF-nn reactive force field, OPLS / L-OPLS fixed-topology
|
|
334
|
+
│ force field, the .frc <-> model parameter bridges
|
|
335
|
+
├── transformer/ shared graph-transformer building blocks
|
|
336
|
+
│ ├── attention.py - EdgeMultiheadAttention (multi-head QKV attention on edges)
|
|
337
|
+
│ └── featurizers/ - ExpNormalSmearing radial basis
|
|
338
|
+
└── hybrid/ GNN + transformer potentials with a physics energy split
|
|
339
|
+
└── models/ - bamboo (BAMBOO graph equivariant transformer), dispersion (D3(CSO))
|
|
340
|
+
└── …
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
</details> <!-- End Package layout -->
|
|
344
|
+
|
|
345
|
+
<details> <!-- Start Examples -->
|
|
346
|
+
<summary><h2 style="display:inline-block">Examples</h2></summary>
|
|
347
|
+
|
|
348
|
+
Runnable, pre-executed notebooks live under `examples/` (`pip install -e
|
|
349
|
+
".[examples]"`). They are grouped by model family, where the leading letter of
|
|
350
|
+
`<xnn>` names the architecture type (`gnn` graph, `cnn` convolutional, `dnn`
|
|
351
|
+
deep/descriptor, `ffnn` force-field, `hybrid` mixed):
|
|
352
|
+
|
|
353
|
+
- **Per-model training and MD** (`examples/<xnn>/<model>/`):
|
|
354
|
+
+ `<model>_argon_train_test.ipynb` and `<model>_argon_density_md.ipynb` for
|
|
355
|
+
MACE, NequIP, Allegro, CACE and PhysNet.
|
|
356
|
+
+ `schnet_rmd17_train.ipynb` and `schnet_ethanol_md.ipynb` for SchNet.
|
|
357
|
+
+ `ani_rmd17_train.ipynb` plus the `ani1*_dataset.ipynb` / `ani2x_dataset.ipynb`
|
|
358
|
+
dataset walk-throughs for ANI.
|
|
359
|
+
+ `les_molecular_dimers.ipynb` for the LES long-range wrapper (charged and
|
|
360
|
+
polar dimers) and `recreate_mace_architecture.ipynb` for a block-by-block
|
|
361
|
+
MACE rebuild.
|
|
362
|
+
+ `bamboo_dimer_electrostatics.ipynb` and `bamboo_charge_analysis.ipynb` for
|
|
363
|
+
the hybrid BAMBOO model.
|
|
364
|
+
- **Force fields** (`examples/ffnn/`):
|
|
365
|
+
+ `reaxff/reaxff_rmd17_train_test.ipynb` trains the ReaxFF-nn reactive force
|
|
366
|
+
field on rMD17 and `reaxff/reaxff_md_bond_orders.ipynb` analyses its bond
|
|
367
|
+
orders, EEM charges and bond dissociation in MD. Both benchmark against the
|
|
368
|
+
published classical Chenoweth 2008 C/H/O field, loaded from the shipped
|
|
369
|
+
SEAMM `.frc` file (`ReaxFF("CHO_cho_2008")`).
|
|
370
|
+
+ `opls/opls_conformational_energetics.ipynb` reproduces Table 1 of the 1996
|
|
371
|
+
OPLS-AA paper with a relaxed dihedral driver, typing every molecule from
|
|
372
|
+
coordinates with the SMARTS templates of `oplsaa.frc`.
|
|
373
|
+
+ `opls/opls_lopls_torsion_refit.ipynb` re-derives the L-OPLS hydrocarbon
|
|
374
|
+
torsion refit of Siu et al. (2012) by gradient descent
|
|
375
|
+
(`trainable=("dihedral_v",)`) and writes the trained field back out as a
|
|
376
|
+
`.frc` file.
|
|
377
|
+
- **Data and deployment:**
|
|
378
|
+
+ `data/load_dataset_tutorial.ipynb` covers the one-line dataset hub used by
|
|
379
|
+
every training notebook (`load_dataset("argon_md")`, `load_dataset("rmd17",
|
|
380
|
+
...)`, `load_dataset("ani1", ...)`, `load_dataset("lode_dimers",
|
|
381
|
+
subset="bio_scan")`).
|
|
382
|
+
+ `deploy/mdi_argon_md.ipynb` and `deploy/mdi_argon_lammps.ipynb` drive a
|
|
383
|
+
trained model from an external MD code through the MDI engine.
|
|
384
|
+
+ `examples/quickstart.py` is a minimal train/predict script on toy data.
|
|
385
|
+
- **Fidelity checks** (`examples/fidelity_checks/<model>_verification.ipynb`):
|
|
386
|
+
+ Block-by-block numerical comparisons against the upstream codes for MACE,
|
|
387
|
+
NequIP, Allegro, CACE, SchNet, PhysNet, ANI, BAMBOO and LES.
|
|
388
|
+
+ OPLS is verified against OpenMM (an independent MD engine, optional
|
|
389
|
+
dependency) in `opls_verification.ipynb` and `tests/test_opls.py`.
|
|
390
|
+
+ **ReaxFF is the exception:** the authors' reference implementation of
|
|
391
|
+
ReaxFF-nn is AGPL-licensed, so no verification notebook or test depending
|
|
392
|
+
on it (and no code derived from it) is distributed with this MIT-licensed
|
|
393
|
+
code base. The implementation follows the published equations, was checked
|
|
394
|
+
against that implementation during development without redistributing
|
|
395
|
+
anything from it, and ships with self-contained equation-by-equation tests
|
|
396
|
+
instead (`tests/test_reaxff.py`; see the fidelity notes in the
|
|
397
|
+
documentation).
|
|
398
|
+
|
|
399
|
+
</details> <!-- End Examples -->
|
|
400
|
+
|
|
401
|
+
<details> <!-- Start Extension points -->
|
|
402
|
+
<summary><h2 style="display:inline-block">Extension points</h2></summary>
|
|
403
|
+
|
|
404
|
+
- **Implement a new model:**
|
|
405
|
+
+ Pick your model family package (`gnn` / `cnn` / `dnn`/ `ffnn`, or add one)
|
|
406
|
+
and add a module under `<family>/models/`.
|
|
407
|
+
+ Subclass `xnn.common.models.InteratomicPotential` (or the family base,
|
|
408
|
+
e.g., `gnn.models.base.EquivariantGNN`) and implement its `forward(data)`
|
|
409
|
+
method.
|
|
410
|
+
+ register your model implementation using `@register_model` decorator.
|
|
411
|
+
+ Add a YAML config file for your model `configs/model/<name>.yaml`.
|
|
412
|
+
+ Import the family package so the model registers.
|
|
413
|
+
+ For TorchScript/LAMMPS export, it is important to expose a scriptable
|
|
414
|
+
`node_energy(atomic_numbers, edge_index, edge_vec)` core (SchNet shows the
|
|
415
|
+
pattern; e3nn models need e3nn's JIT support for this).
|
|
416
|
+
- **Add a new featurizer:**
|
|
417
|
+
+ Subclass `xnn.common.featurizers.Featurizer` and implement `output_dim` and
|
|
418
|
+
`forward(data)`. Put the resulting featurizer module in the
|
|
419
|
+
`common/featurizers/` if shared by more than one model family or under the
|
|
420
|
+
using family's `featurizers/` if it is only used by that one model family.
|
|
421
|
+
|
|
422
|
+
</details> <!-- End Extension points -->
|