aimnet 0.0.1__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.
- aimnet-0.0.1/LICENSE +21 -0
- aimnet-0.0.1/PKG-INFO +78 -0
- aimnet-0.0.1/README.md +49 -0
- aimnet-0.0.1/aimnet/__init__.py +0 -0
- aimnet-0.0.1/aimnet/base.py +41 -0
- aimnet-0.0.1/aimnet/calculators/__init__.py +15 -0
- aimnet-0.0.1/aimnet/calculators/aimnet2ase.py +98 -0
- aimnet-0.0.1/aimnet/calculators/aimnet2pysis.py +76 -0
- aimnet-0.0.1/aimnet/calculators/calculator.py +320 -0
- aimnet-0.0.1/aimnet/calculators/model_registry.py +60 -0
- aimnet-0.0.1/aimnet/calculators/model_registry.yaml +33 -0
- aimnet-0.0.1/aimnet/calculators/nb_kernel_cpu.py +222 -0
- aimnet-0.0.1/aimnet/calculators/nb_kernel_cuda.py +217 -0
- aimnet-0.0.1/aimnet/calculators/nbmat.py +220 -0
- aimnet-0.0.1/aimnet/cli.py +22 -0
- aimnet-0.0.1/aimnet/config.py +170 -0
- aimnet-0.0.1/aimnet/constants.py +467 -0
- aimnet-0.0.1/aimnet/data/__init__.py +1 -0
- aimnet-0.0.1/aimnet/data/sgdataset.py +517 -0
- aimnet-0.0.1/aimnet/dftd3_data.pt +0 -0
- aimnet-0.0.1/aimnet/models/__init__.py +2 -0
- aimnet-0.0.1/aimnet/models/aimnet2.py +188 -0
- aimnet-0.0.1/aimnet/models/aimnet2.yaml +44 -0
- aimnet-0.0.1/aimnet/models/aimnet2_dftd3_wb97m.yaml +51 -0
- aimnet-0.0.1/aimnet/models/base.py +51 -0
- aimnet-0.0.1/aimnet/modules/__init__.py +3 -0
- aimnet-0.0.1/aimnet/modules/aev.py +201 -0
- aimnet-0.0.1/aimnet/modules/core.py +237 -0
- aimnet-0.0.1/aimnet/modules/lr.py +243 -0
- aimnet-0.0.1/aimnet/nbops.py +151 -0
- aimnet-0.0.1/aimnet/ops.py +208 -0
- aimnet-0.0.1/aimnet/train/__init__.py +0 -0
- aimnet-0.0.1/aimnet/train/calc_sae.py +43 -0
- aimnet-0.0.1/aimnet/train/default_train.yaml +166 -0
- aimnet-0.0.1/aimnet/train/loss.py +83 -0
- aimnet-0.0.1/aimnet/train/metrics.py +188 -0
- aimnet-0.0.1/aimnet/train/pt2jpt.py +81 -0
- aimnet-0.0.1/aimnet/train/train.py +155 -0
- aimnet-0.0.1/aimnet/train/utils.py +398 -0
- aimnet-0.0.1/pyproject.toml +143 -0
aimnet-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, Roman Zubatyuk
|
|
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.
|
aimnet-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: aimnet
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: AIMNet Machine Learned Interatomic Potential
|
|
5
|
+
Home-page: https://github.com/isayevlab/aimnetcentral
|
|
6
|
+
Author: Roman Zubatyuk
|
|
7
|
+
Author-email: zubatyuk@gmail.com
|
|
8
|
+
Requires-Python: >=3.10,<4.0
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
15
|
+
Requires-Dist: h5py (>=3.12.1,<4.0.0)
|
|
16
|
+
Requires-Dist: ignite (>=1.1.0,<2.0.0)
|
|
17
|
+
Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
|
|
18
|
+
Requires-Dist: numba (>=0.60.0,<0.61.0)
|
|
19
|
+
Requires-Dist: numpy (<2.0)
|
|
20
|
+
Requires-Dist: omegaconf (>=2.3.0,<3.0.0)
|
|
21
|
+
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
|
|
22
|
+
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
|
23
|
+
Requires-Dist: torch (>=2.5.0,<3.0.0)
|
|
24
|
+
Requires-Dist: wandb (>=0.18.5,<0.19.0)
|
|
25
|
+
Project-URL: Documentation, https://isayevlab.github.io/aimnetcentral/
|
|
26
|
+
Project-URL: Repository, https://github.com/isayevlab/aimnetcentral
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# aimnetcentral
|
|
30
|
+
|
|
31
|
+
[](https://img.shields.io/github/v/release/isayevlab/aimnetcentral)
|
|
32
|
+
[](https://github.com/isayevlab/aimnetcentral/actions/workflows/main.yml?query=branch%3Amain)
|
|
33
|
+
[](https://codecov.io/gh/isayevlab/aimnetcentral)
|
|
34
|
+
[](https://img.shields.io/github/commit-activity/m/isayevlab/aimnetcentral)
|
|
35
|
+
[](https://img.shields.io/github/license/isayevlab/aimnetcentral)
|
|
36
|
+
|
|
37
|
+
AIMNet Machine Learned Interatomic Potential
|
|
38
|
+
|
|
39
|
+
- **Github repository**: <https://github.com/isayevlab/aimnetcentral/>
|
|
40
|
+
- **Documentation** <https://isayevlab.github.io/aimnetcentral/>
|
|
41
|
+
|
|
42
|
+
## Getting started with your project
|
|
43
|
+
|
|
44
|
+
First, create a repository on GitHub with the same name as this project, and then run the following commands:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git init -b main
|
|
48
|
+
git add .
|
|
49
|
+
git commit -m "init commit"
|
|
50
|
+
git remote add origin git@github.com:isayevlab/aimnetcentral.git
|
|
51
|
+
git push -u origin main
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Finally, install the environment and the pre-commit hooks with
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
make install
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
You are now ready to start development on your project!
|
|
61
|
+
The CI/CD pipeline will be triggered when you open a pull request, merge to main, or when you create a new release.
|
|
62
|
+
|
|
63
|
+
To finalize the set-up for publishing to PyPI or Artifactory, see [here](https://fpgmaas.github.io/cookiecutter-poetry/features/publishing/#set-up-for-pypi).
|
|
64
|
+
For activating the automatic documentation with MkDocs, see [here](https://fpgmaas.github.io/cookiecutter-poetry/features/mkdocs/#enabling-the-documentation-on-github).
|
|
65
|
+
To enable the code coverage reports, see [here](https://fpgmaas.github.io/cookiecutter-poetry/features/codecov/).
|
|
66
|
+
|
|
67
|
+
## Releasing a new version
|
|
68
|
+
|
|
69
|
+
- Create an API Token on [PyPI](https://pypi.org/).
|
|
70
|
+
- Add the API Token to your projects secrets with the name `PYPI_TOKEN` by visiting [this page](https://github.com/isayevlab/aimnetcentral/settings/secrets/actions/new).
|
|
71
|
+
- Create a [new release](https://github.com/isayevlab/aimnetcentral/releases/new) on Github.
|
|
72
|
+
- Create a new tag in the form `*.*.*`.
|
|
73
|
+
- For more details, see [here](https://fpgmaas.github.io/cookiecutter-poetry/features/cicd/#how-to-trigger-a-release).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
Repository initiated with [fpgmaas/cookiecutter-poetry](https://github.com/fpgmaas/cookiecutter-poetry).
|
|
78
|
+
|
aimnet-0.0.1/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# aimnetcentral
|
|
2
|
+
|
|
3
|
+
[](https://img.shields.io/github/v/release/isayevlab/aimnetcentral)
|
|
4
|
+
[](https://github.com/isayevlab/aimnetcentral/actions/workflows/main.yml?query=branch%3Amain)
|
|
5
|
+
[](https://codecov.io/gh/isayevlab/aimnetcentral)
|
|
6
|
+
[](https://img.shields.io/github/commit-activity/m/isayevlab/aimnetcentral)
|
|
7
|
+
[](https://img.shields.io/github/license/isayevlab/aimnetcentral)
|
|
8
|
+
|
|
9
|
+
AIMNet Machine Learned Interatomic Potential
|
|
10
|
+
|
|
11
|
+
- **Github repository**: <https://github.com/isayevlab/aimnetcentral/>
|
|
12
|
+
- **Documentation** <https://isayevlab.github.io/aimnetcentral/>
|
|
13
|
+
|
|
14
|
+
## Getting started with your project
|
|
15
|
+
|
|
16
|
+
First, create a repository on GitHub with the same name as this project, and then run the following commands:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
git init -b main
|
|
20
|
+
git add .
|
|
21
|
+
git commit -m "init commit"
|
|
22
|
+
git remote add origin git@github.com:isayevlab/aimnetcentral.git
|
|
23
|
+
git push -u origin main
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Finally, install the environment and the pre-commit hooks with
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
make install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
You are now ready to start development on your project!
|
|
33
|
+
The CI/CD pipeline will be triggered when you open a pull request, merge to main, or when you create a new release.
|
|
34
|
+
|
|
35
|
+
To finalize the set-up for publishing to PyPI or Artifactory, see [here](https://fpgmaas.github.io/cookiecutter-poetry/features/publishing/#set-up-for-pypi).
|
|
36
|
+
For activating the automatic documentation with MkDocs, see [here](https://fpgmaas.github.io/cookiecutter-poetry/features/mkdocs/#enabling-the-documentation-on-github).
|
|
37
|
+
To enable the code coverage reports, see [here](https://fpgmaas.github.io/cookiecutter-poetry/features/codecov/).
|
|
38
|
+
|
|
39
|
+
## Releasing a new version
|
|
40
|
+
|
|
41
|
+
- Create an API Token on [PyPI](https://pypi.org/).
|
|
42
|
+
- Add the API Token to your projects secrets with the name `PYPI_TOKEN` by visiting [this page](https://github.com/isayevlab/aimnetcentral/settings/secrets/actions/new).
|
|
43
|
+
- Create a [new release](https://github.com/isayevlab/aimnetcentral/releases/new) on Github.
|
|
44
|
+
- Create a new tag in the form `*.*.*`.
|
|
45
|
+
- For more details, see [here](https://fpgmaas.github.io/cookiecutter-poetry/features/cicd/#how-to-trigger-a-release).
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
Repository initiated with [fpgmaas/cookiecutter-poetry](https://github.com/fpgmaas/cookiecutter-poetry).
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import ClassVar, Dict, Final
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
from torch import Tensor, nn
|
|
5
|
+
|
|
6
|
+
from aimnet import nbops
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AIMNet2Base(nn.Module): # pylint: disable=abstract-method
|
|
10
|
+
"""Base class for AIMNet2 models. Implements pre-processing data:
|
|
11
|
+
converting to right dtype and device, setting nb mode, calculating masks.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
_required_keys: Final = ["coord", "numbers", "charge"]
|
|
15
|
+
_required_keys_dtype: Final = [torch.float32, torch.int64, torch.float32]
|
|
16
|
+
_optional_keys: Final = ["mult", "nbmat", "nbmat_lr", "mol_idx", "shifts", "cell"]
|
|
17
|
+
_optional_keys_dtype: Final = [torch.float32, torch.int64, torch.int64, torch.int64, torch.float32, torch.float32]
|
|
18
|
+
__constants__: ClassVar = ["_required_keys", "_required_keys_dtype", "_optional_keys", "_optional_keys_dtype"]
|
|
19
|
+
|
|
20
|
+
def __init__(self):
|
|
21
|
+
super().__init__()
|
|
22
|
+
|
|
23
|
+
def _prepare_dtype(self, data: Dict[str, Tensor]) -> Dict[str, Tensor]:
|
|
24
|
+
for k, d in zip(self._required_keys, self._required_keys_dtype):
|
|
25
|
+
assert k in data, f"Key {k} is required"
|
|
26
|
+
data[k] = data[k].to(d)
|
|
27
|
+
for k, d in zip(self._optional_keys, self._optional_keys_dtype):
|
|
28
|
+
if k in data:
|
|
29
|
+
data[k] = data[k].to(d)
|
|
30
|
+
return data
|
|
31
|
+
|
|
32
|
+
def prepare_input(self, data: Dict[str, Tensor]) -> Dict[str, Tensor]:
|
|
33
|
+
"""Some sommon operations"""
|
|
34
|
+
data = self._prepare_dtype(data)
|
|
35
|
+
data = nbops.set_nb_mode(data)
|
|
36
|
+
data = nbops.calc_masks(data)
|
|
37
|
+
|
|
38
|
+
assert data["charge"].ndim == 1, "Charge should be 1D tensor."
|
|
39
|
+
if "mult" in data:
|
|
40
|
+
assert data["mult"].ndim == 1, "Mult should be 1D tensor."
|
|
41
|
+
return data
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import importlib.util
|
|
2
|
+
|
|
3
|
+
from .calculator import AIMNet2Calculator
|
|
4
|
+
|
|
5
|
+
__all__ = ["AIMNet2Calculator"]
|
|
6
|
+
|
|
7
|
+
if importlib.util.find_spec("ase") is not None:
|
|
8
|
+
from .aimnet2ase import AIMNet2ASE
|
|
9
|
+
|
|
10
|
+
__all__.append(AIMNet2ASE) # type: ignore
|
|
11
|
+
|
|
12
|
+
if importlib.util.find_spec("pysisyphus") is not None:
|
|
13
|
+
from .aimnet2pysis import AIMNet2Pysis
|
|
14
|
+
|
|
15
|
+
__all__.append(AIMNet2Pysis) # type: ignore
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import torch
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from ase.calculators.calculator import Calculator, all_changes # type: ignore
|
|
6
|
+
except ImportError:
|
|
7
|
+
raise ImportError("ASE is not installed. Please install ASE to use this module.") from None
|
|
8
|
+
|
|
9
|
+
from .calculator import AIMNet2Calculator
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AIMNet2ASE(Calculator):
|
|
13
|
+
from typing import ClassVar
|
|
14
|
+
|
|
15
|
+
implemented_properties: ClassVar[list[str]] = ["energy", "forces", "free_energy", "charges", "stress"]
|
|
16
|
+
|
|
17
|
+
def __init__(self, base_calc: AIMNet2Calculator | str = "aimnet2", charge=0, mult=1):
|
|
18
|
+
super().__init__()
|
|
19
|
+
if isinstance(base_calc, str):
|
|
20
|
+
base_calc = AIMNet2Calculator(base_calc)
|
|
21
|
+
self.base_calc = base_calc
|
|
22
|
+
self.charge = charge
|
|
23
|
+
self.mult = mult
|
|
24
|
+
self.reset()
|
|
25
|
+
# list of implemented species
|
|
26
|
+
if hasattr(base_calc, "implemented_species"):
|
|
27
|
+
self.implemented_species = base_calc.implemented_species.cpu().numpy() # type: ignore
|
|
28
|
+
else:
|
|
29
|
+
self.implemented_species = None
|
|
30
|
+
|
|
31
|
+
def reset(self):
|
|
32
|
+
super().reset()
|
|
33
|
+
self._t_numbers = None
|
|
34
|
+
self._t_charge = None
|
|
35
|
+
self._t_mult = None
|
|
36
|
+
self.charge = 0.0
|
|
37
|
+
self.mult = 1.0
|
|
38
|
+
|
|
39
|
+
def set_atoms(self, atoms):
|
|
40
|
+
if self.implemented_species is not None and not np.in1d(atoms.numbers, self.implemented_species).all():
|
|
41
|
+
raise ValueError("Some species are not implemented in the AIMNet2Calculator")
|
|
42
|
+
self.reset()
|
|
43
|
+
self.atoms = atoms
|
|
44
|
+
|
|
45
|
+
def set_charge(self, charge):
|
|
46
|
+
self.charge = charge
|
|
47
|
+
self._t_charge = None
|
|
48
|
+
self.update_tensors()
|
|
49
|
+
|
|
50
|
+
def set_mult(self, mult):
|
|
51
|
+
self.mult = mult
|
|
52
|
+
self._t_mult = None
|
|
53
|
+
self.update_tensors()
|
|
54
|
+
|
|
55
|
+
def update_tensors(self):
|
|
56
|
+
if self._t_numbers is None:
|
|
57
|
+
self._t_numbers = torch.tensor(self.atoms.numbers, dtype=torch.int64, device=self.base_calc.device)
|
|
58
|
+
if self._t_charge is None:
|
|
59
|
+
self._t_charge = torch.tensor(self.charge, dtype=torch.float32, device=self.base_calc.device)
|
|
60
|
+
if self._t_mult is None:
|
|
61
|
+
self._t_mult = torch.tensor(self.mult, dtype=torch.float32, device=self.base_calc.device)
|
|
62
|
+
|
|
63
|
+
def calculate(self, atoms=None, properties=None, system_changes=all_changes):
|
|
64
|
+
if properties is None:
|
|
65
|
+
properties = ["energy"]
|
|
66
|
+
super().calculate(atoms, properties, system_changes)
|
|
67
|
+
self.update_tensors()
|
|
68
|
+
|
|
69
|
+
cell = self.atoms.cell.array if self.atoms.cell is not None and self.atoms.pbc.any() else None
|
|
70
|
+
|
|
71
|
+
_in = {
|
|
72
|
+
"coord": torch.tensor(self.atoms.positions, dtype=torch.float32, device=self.base_calc.device),
|
|
73
|
+
"numbers": self._t_numbers,
|
|
74
|
+
"charge": self._t_charge,
|
|
75
|
+
"mult": self._t_mult,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_unsqueezed = False
|
|
79
|
+
if cell is not None:
|
|
80
|
+
_in["cell"] = cell
|
|
81
|
+
else:
|
|
82
|
+
for k, v in _in.items():
|
|
83
|
+
_in[k] = v.unsqueeze(0)
|
|
84
|
+
_unsqueezed = True
|
|
85
|
+
|
|
86
|
+
results = self.base_calc(_in, forces="forces" in properties, stress="stress" in properties)
|
|
87
|
+
|
|
88
|
+
for k, v in results.items():
|
|
89
|
+
if _unsqueezed:
|
|
90
|
+
v = v.squeeze(0)
|
|
91
|
+
results[k] = v.detach().cpu().numpy() # type: ignore
|
|
92
|
+
|
|
93
|
+
self.results["energy"] = results["energy"]
|
|
94
|
+
self.results["charges"] = results["charges"]
|
|
95
|
+
if "forces" in properties:
|
|
96
|
+
self.results["forces"] = results["forces"]
|
|
97
|
+
if "stress" in properties:
|
|
98
|
+
self.results["stress"] = results["stress"]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from typing import ClassVar
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
|
|
5
|
+
from .calculator import AIMNet2Calculator
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
import pysisyphus.run # type: ignore
|
|
9
|
+
from pysisyphus.calculators.Calculator import Calculator # type: ignore
|
|
10
|
+
from pysisyphus.constants import ANG2BOHR, AU2EV, BOHR2ANG # type: ignore
|
|
11
|
+
from pysisyphus.elem_data import ATOMIC_NUMBERS # type: ignore
|
|
12
|
+
except ImportError:
|
|
13
|
+
raise ImportError("Pysisyphus is not installed. Please install Pysisyphus to use this module.") from None
|
|
14
|
+
|
|
15
|
+
EV2AU = 1 / AU2EV
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AIMNet2Pysis(Calculator):
|
|
19
|
+
implemented_properties: ClassVar = ["energy", "forces", "free_energy", "charges", "stress"]
|
|
20
|
+
|
|
21
|
+
def __init__(self, model: AIMNet2Calculator | str = "aimnet2", charge=0, mult=1, **kwargs):
|
|
22
|
+
super().__init__(charge=charge, mult=mult, **kwargs)
|
|
23
|
+
if isinstance(model, str):
|
|
24
|
+
model = AIMNet2Calculator(model)
|
|
25
|
+
self.model = model
|
|
26
|
+
|
|
27
|
+
def _prepere_input(self, atoms, coord):
|
|
28
|
+
device = self.model.device
|
|
29
|
+
numbers = torch.as_tensor([ATOMIC_NUMBERS[a.lower()] for a in atoms], device=device)
|
|
30
|
+
coord = torch.as_tensor(coord, dtype=torch.float, device=device).view(-1, 3) * BOHR2ANG
|
|
31
|
+
charge = torch.as_tensor([self.charge], dtype=torch.float, device=device)
|
|
32
|
+
mult = torch.as_tensor([self.mult], dtype=torch.float, device=device)
|
|
33
|
+
return {"coord": coord, "numbers": numbers, "charge": charge, "mult": mult}
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def _results_get_energy(results):
|
|
37
|
+
return results["energy"].item() * EV2AU
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def _results_get_forces(results):
|
|
41
|
+
return (results["forces"].detach() * (EV2AU / ANG2BOHR)).flatten().to(torch.double).cpu().numpy()
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def _results_get_hessian(results):
|
|
45
|
+
return (
|
|
46
|
+
(results["hessian"].flatten(0, 1).flatten(-2, -1) * (EV2AU / ANG2BOHR / ANG2BOHR))
|
|
47
|
+
.to(torch.double)
|
|
48
|
+
.cpu()
|
|
49
|
+
.numpy()
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def get_energy(self, atoms, coords):
|
|
53
|
+
_in = self._prepere_input(atoms, coords)
|
|
54
|
+
res = self.model(_in)
|
|
55
|
+
energy = self._results_get_energy(res)
|
|
56
|
+
return {"energy": energy}
|
|
57
|
+
|
|
58
|
+
def get_forces(self, atoms, coords):
|
|
59
|
+
_in = self._prepere_input(atoms, coords)
|
|
60
|
+
res = self.model(_in, forces=True)
|
|
61
|
+
energy = self._results_get_energy(res)
|
|
62
|
+
forces = self._results_get_forces(res)
|
|
63
|
+
return {"energy": energy, "forces": forces}
|
|
64
|
+
|
|
65
|
+
def get_hessian(self, atoms, coords):
|
|
66
|
+
_in = self._prepere_input(atoms, coords)
|
|
67
|
+
res = self.model(_in, forces=True, hessian=True)
|
|
68
|
+
energy = self._results_get_energy(res)
|
|
69
|
+
forces = self._results_get_forces(res)
|
|
70
|
+
hessian = self._results_get_hessian(res)
|
|
71
|
+
return {"energy": energy, "forces": forces, "hessian": hessian}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def run_pysis():
|
|
75
|
+
pysisyphus.run.CALC_DICT["aimnet"] = AIMNet2Pysis
|
|
76
|
+
pysisyphus.run.run()
|