BUCToolkit 1.0b0__py3-none-any.whl
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.
- BUCToolkit/BatchGenerate/CheckStructures.py +198 -0
- BUCToolkit/BatchGenerate/__init__.py +6 -0
- BUCToolkit/BatchGenerate/coords_interp.py +127 -0
- BUCToolkit/BatchGenerate/initial_ads_structures.py +351 -0
- BUCToolkit/BatchGenerate/random_replace.py +88 -0
- BUCToolkit/BatchMC/MetropolisMC.py +210 -0
- BUCToolkit/BatchMC/_BaseMC.py +863 -0
- BUCToolkit/BatchMC/__init__.py +8 -0
- BUCToolkit/BatchMD/BiasedMD.py +276 -0
- BUCToolkit/BatchMD/NVE.py +92 -0
- BUCToolkit/BatchMD/NVT.py +510 -0
- BUCToolkit/BatchMD/_BaseMD.py +1251 -0
- BUCToolkit/BatchMD/__init__.py +18 -0
- BUCToolkit/BatchMD/constrained_md/BiasedMD.py +273 -0
- BUCToolkit/BatchMD/constrained_md/ConstrNVE.py +169 -0
- BUCToolkit/BatchMD/constrained_md/ConstrNVT.py +462 -0
- BUCToolkit/BatchMD/constrained_md/NVE.py +78 -0
- BUCToolkit/BatchMD/constrained_md/NVT.py +346 -0
- BUCToolkit/BatchMD/constrained_md/_BaseMD.py +440 -0
- BUCToolkit/BatchMD/constrained_md/_ConstrBaseMD.py +607 -0
- BUCToolkit/BatchMD/constrained_md/__init__.py +18 -0
- BUCToolkit/BatchOptim/TS/CI_NEB.py +286 -0
- BUCToolkit/BatchOptim/TS/Dimer.py +950 -0
- BUCToolkit/BatchOptim/TS/__init__.py +10 -0
- BUCToolkit/BatchOptim/_BaseOpt.py +702 -0
- BUCToolkit/BatchOptim/__init__.py +22 -0
- BUCToolkit/BatchOptim/_utils/__init__.py +6 -0
- BUCToolkit/BatchOptim/_utils/_line_search.py +972 -0
- BUCToolkit/BatchOptim/_utils/_warnings.py +11 -0
- BUCToolkit/BatchOptim/frequency.py +496 -0
- BUCToolkit/BatchOptim/minimize/CG.py +256 -0
- BUCToolkit/BatchOptim/minimize/FIRE.py +310 -0
- BUCToolkit/BatchOptim/minimize/QN.py +205 -0
- BUCToolkit/BatchOptim/minimize/__init__.py +17 -0
- BUCToolkit/BatchStructures/BatchStructuresBase.py +2261 -0
- BUCToolkit/BatchStructures/StructuresIO.py +1394 -0
- BUCToolkit/BatchStructures/__init__.py +15 -0
- BUCToolkit/Preprocessing/__init__.py +7 -0
- BUCToolkit/Preprocessing/load_files.py +1680 -0
- BUCToolkit/Preprocessing/preprocessing.py +923 -0
- BUCToolkit/Preprocessing/sampling.py +299 -0
- BUCToolkit/Preprocessing/supercells.py +140 -0
- BUCToolkit/Preprocessing/write_files.py +524 -0
- BUCToolkit/StandardTemplate.py +417 -0
- BUCToolkit/__init__.py +33 -0
- BUCToolkit/_version.py +7 -0
- BUCToolkit/api/ConstrainedMolecularDynamics.py +347 -0
- BUCToolkit/api/DataLoaders.py +321 -0
- BUCToolkit/api/Losses.py +170 -0
- BUCToolkit/api/Metrics.py +84 -0
- BUCToolkit/api/ModelOptims.py +296 -0
- BUCToolkit/api/MolecularDynamics.py +282 -0
- BUCToolkit/api/MonteCarlo.py +280 -0
- BUCToolkit/api/NEB.py +325 -0
- BUCToolkit/api/Predictor.py +292 -0
- BUCToolkit/api/StructureOptimization.py +484 -0
- BUCToolkit/api/Trainer.py +635 -0
- BUCToolkit/api/VibrationAnalysis.py +279 -0
- BUCToolkit/api/__init__.py +38 -0
- BUCToolkit/api/_io.py +1026 -0
- BUCToolkit/cli/__init__.py +20 -0
- BUCToolkit/cli/cli.py +934 -0
- BUCToolkit/cli/input_stub.py +140 -0
- BUCToolkit/cli/main.py +368 -0
- BUCToolkit/cli/print_logo.py +149 -0
- BUCToolkit/cli/template_model.py +6 -0
- BUCToolkit/io.py +30 -0
- BUCToolkit/utils/AtomSelector.py +64 -0
- BUCToolkit/utils/AtomicNumber2Properties.py +39 -0
- BUCToolkit/utils/ElemListReduce.py +52 -0
- BUCToolkit/utils/Ewald.py +210 -0
- BUCToolkit/utils/IrregularTensorReformat.py +59 -0
- BUCToolkit/utils/_CheckModules.py +30 -0
- BUCToolkit/utils/_Element_info.py +527 -0
- BUCToolkit/utils/__init__.py +22 -0
- BUCToolkit/utils/_para_flatt_list.py +131 -0
- BUCToolkit/utils/_print_formatter.py +59 -0
- BUCToolkit/utils/check_structures.py +204 -0
- BUCToolkit/utils/function_utils.py +147 -0
- BUCToolkit/utils/grad_functions.py +69 -0
- BUCToolkit/utils/index_ops.py +432 -0
- BUCToolkit/utils/setup_loggers.py +137 -0
- buctoolkit-1.0b0.dist-info/METADATA +28 -0
- buctoolkit-1.0b0.dist-info/RECORD +88 -0
- buctoolkit-1.0b0.dist-info/WHEEL +5 -0
- buctoolkit-1.0b0.dist-info/entry_points.txt +6 -0
- buctoolkit-1.0b0.dist-info/licenses/LICENSE +21 -0
- buctoolkit-1.0b0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# Copyright (c) 2025.7.4, BUCToolkit.
|
|
2
|
+
# Authors: Pu Pengxin, Song Xin
|
|
3
|
+
# Version: 0.9a
|
|
4
|
+
# File: BiasedMD.py
|
|
5
|
+
# Environment: Python 3.12
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
from typing import Iterable, Dict, Any, List, Literal, Optional, Callable, Sequence, Tuple # noqa: F401
|
|
9
|
+
import warnings
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
import torch as th
|
|
13
|
+
from torch import nn
|
|
14
|
+
|
|
15
|
+
from ._BaseMD import _BaseMD
|
|
16
|
+
from .NVT import NVT
|
|
17
|
+
from .NVE import NVE
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BiasedMD(NVT):
|
|
21
|
+
"""
|
|
22
|
+
Performing MD with given external-biased potentials.
|
|
23
|
+
"""
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
time_step: float,
|
|
27
|
+
max_step: int,
|
|
28
|
+
thermostat: Literal['Langevin', 'VR', 'Nose-Hoover', 'CSVR'],
|
|
29
|
+
thermostat_config: Dict | None = None,
|
|
30
|
+
T_init: float = 298.15,
|
|
31
|
+
output_file: str | None = None,
|
|
32
|
+
output_structures_per_step: int = 1,
|
|
33
|
+
device: str | th.device = 'cpu',
|
|
34
|
+
verbose: int = 2
|
|
35
|
+
):
|
|
36
|
+
super().__init__(
|
|
37
|
+
time_step,
|
|
38
|
+
max_step,
|
|
39
|
+
thermostat,
|
|
40
|
+
thermostat_config,
|
|
41
|
+
T_init,
|
|
42
|
+
output_file,
|
|
43
|
+
output_structures_per_step,
|
|
44
|
+
device,
|
|
45
|
+
verbose
|
|
46
|
+
)
|
|
47
|
+
self.ext_pot_grad_kwargs = None
|
|
48
|
+
self.ext_pot_grad_args = None
|
|
49
|
+
self.ext_pot_grad = None
|
|
50
|
+
self.ext_pot_kwargs = None
|
|
51
|
+
self.ext_pot_args = None
|
|
52
|
+
self.ext_pot = None
|
|
53
|
+
self.__is_set_ext_func = False
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def _auto_grad_func(X: th.Tensor, y: th.Tensor | None = None):
|
|
57
|
+
grad_shape = th.ones_like(y)
|
|
58
|
+
g = th.autograd.grad(y, X, grad_shape)
|
|
59
|
+
return g[0]
|
|
60
|
+
|
|
61
|
+
def set_external_potential(
|
|
62
|
+
self,
|
|
63
|
+
potential_func: Callable,
|
|
64
|
+
potential_grad_func: Callable | None = None,
|
|
65
|
+
func_args:Tuple = tuple(),
|
|
66
|
+
func_kwargs: None | Dict = None,
|
|
67
|
+
grad_func_args: Tuple = tuple(),
|
|
68
|
+
grad_func_kwargs: None | Dict = None,
|
|
69
|
+
is_grad_contain_y: bool = True,
|
|
70
|
+
#is_dynamic: bool = False
|
|
71
|
+
):
|
|
72
|
+
"""
|
|
73
|
+
Set the external potential function.
|
|
74
|
+
Args:
|
|
75
|
+
potential_func: the function of external potential
|
|
76
|
+
potential_grad_func: the gradient of external potential. if None, torch.autograd is applied.
|
|
77
|
+
func_args: arguments of `potential_func`
|
|
78
|
+
func_kwargs: key words arguments of `potential_func`
|
|
79
|
+
grad_func_args: arguments of `potential_grad_func`
|
|
80
|
+
grad_func_kwargs: key words arguments of `potential_grad_func`
|
|
81
|
+
is_grad_contain_y: whether `potential_grad_func` needs dependent variable y as input. if True, potential_grad_func = g(X, y), else g(X)
|
|
82
|
+
#is_dynamic: whether potential function containing time as independent variables. if True, potential_func = f(X, t), else f(X).
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
|
|
86
|
+
"""
|
|
87
|
+
if func_kwargs is None: func_kwargs = {}
|
|
88
|
+
if grad_func_kwargs is None: grad_func_kwargs = {}
|
|
89
|
+
self.ext_pot = potential_func
|
|
90
|
+
self.ext_pot_args = func_args
|
|
91
|
+
self.ext_pot_kwargs = func_kwargs
|
|
92
|
+
# ext_grad_func
|
|
93
|
+
if potential_grad_func is None:
|
|
94
|
+
self.ext_pot_grad = self._auto_grad_func
|
|
95
|
+
else:
|
|
96
|
+
self.ext_pot_grad = potential_grad_func
|
|
97
|
+
|
|
98
|
+
self.ext_pot_grad_args = grad_func_args
|
|
99
|
+
self.ext_pot_grad_kwargs = grad_func_kwargs
|
|
100
|
+
self.is_grad_contain_y = is_grad_contain_y
|
|
101
|
+
#self.is_dynamic = is_dynamic
|
|
102
|
+
self.__is_set_ext_func = True
|
|
103
|
+
|
|
104
|
+
def run(
|
|
105
|
+
self,
|
|
106
|
+
func: Any | nn.Module,
|
|
107
|
+
X: th.Tensor,
|
|
108
|
+
Element_list: List[List[str]] | List[List[int]],
|
|
109
|
+
V_init: th.Tensor | None = None,
|
|
110
|
+
grad_func: Any | nn.Module = None,
|
|
111
|
+
func_args: Tuple|List = tuple(),
|
|
112
|
+
func_kwargs: Dict | None = None,
|
|
113
|
+
grad_func_args: Tuple|List = tuple(),
|
|
114
|
+
grad_func_kwargs: Dict | None = None,
|
|
115
|
+
is_grad_func_contain_y: bool = True,
|
|
116
|
+
require_grad: bool = False,
|
|
117
|
+
batch_indices: List[int] | Tuple[int, ...] | th.Tensor | np.ndarray | None = None,
|
|
118
|
+
fixed_atom_tensor: Optional[th.Tensor] = None,
|
|
119
|
+
is_fix_mass_center: bool = False
|
|
120
|
+
) -> None:
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
func:
|
|
125
|
+
X:
|
|
126
|
+
Element_list:
|
|
127
|
+
V_init:
|
|
128
|
+
grad_func:
|
|
129
|
+
func_args:
|
|
130
|
+
func_kwargs:
|
|
131
|
+
grad_func_args:
|
|
132
|
+
grad_func_kwargs:
|
|
133
|
+
is_grad_func_contain_y:
|
|
134
|
+
require_grad:
|
|
135
|
+
batch_indices:
|
|
136
|
+
fixed_atom_tensor:
|
|
137
|
+
is_fix_mass_center:
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
|
|
141
|
+
"""
|
|
142
|
+
if func_kwargs is None: func_kwargs = dict()
|
|
143
|
+
if grad_func_kwargs is None: grad_func_kwargs = dict()
|
|
144
|
+
if grad_func is not None:
|
|
145
|
+
_grad_func = grad_func
|
|
146
|
+
else:
|
|
147
|
+
_grad_func = self._auto_grad_func
|
|
148
|
+
is_grad_func_contain_y = True
|
|
149
|
+
|
|
150
|
+
if self.__is_set_ext_func:
|
|
151
|
+
wrapper = _FuncWrapperWithExtPot(
|
|
152
|
+
func,
|
|
153
|
+
self.ext_pot,
|
|
154
|
+
_grad_func,
|
|
155
|
+
self.ext_pot_grad,
|
|
156
|
+
len(func_args),
|
|
157
|
+
func_kwargs.keys(),
|
|
158
|
+
len(grad_func_args),
|
|
159
|
+
grad_func_kwargs.keys()
|
|
160
|
+
)
|
|
161
|
+
wrapped_args = func_args + self.ext_pot_args
|
|
162
|
+
wrapped_kwargs = func_kwargs.update(self.ext_pot_kwargs)
|
|
163
|
+
wrapped_grad_args = grad_func_args + self.ext_pot_grad_args
|
|
164
|
+
wrapped_grad_kwargs = grad_func_kwargs.update(self.ext_pot_grad_kwargs)
|
|
165
|
+
|
|
166
|
+
wrapped_func = wrapper.Energy
|
|
167
|
+
if self.is_grad_contain_y:
|
|
168
|
+
wrapped_grad_func = wrapper.Grad_y
|
|
169
|
+
else:
|
|
170
|
+
wrapped_grad_func = wrapper.Grad
|
|
171
|
+
|
|
172
|
+
res = super().run(
|
|
173
|
+
wrapped_func,
|
|
174
|
+
X,
|
|
175
|
+
Element_list,
|
|
176
|
+
V_init,
|
|
177
|
+
wrapped_grad_func,
|
|
178
|
+
wrapped_args,
|
|
179
|
+
wrapped_kwargs,
|
|
180
|
+
wrapped_grad_args,
|
|
181
|
+
wrapped_grad_kwargs,
|
|
182
|
+
is_grad_func_contain_y,
|
|
183
|
+
require_grad,
|
|
184
|
+
batch_indices,
|
|
185
|
+
fixed_atom_tensor,
|
|
186
|
+
is_fix_mass_center
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return res
|
|
190
|
+
else:
|
|
191
|
+
raise RuntimeError(f'The external potential function is not set.')
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class _FuncWrapperWithExtPot:
|
|
195
|
+
def __init__(
|
|
196
|
+
self,
|
|
197
|
+
func,
|
|
198
|
+
ext_func,
|
|
199
|
+
grad_func,
|
|
200
|
+
ext_grad_func,
|
|
201
|
+
n_func_args = 0,
|
|
202
|
+
k_func_kwargs = None,
|
|
203
|
+
n_grad_func_args = 0,
|
|
204
|
+
k_grad_func_kwargs = None,
|
|
205
|
+
|
|
206
|
+
) -> None:
|
|
207
|
+
"""
|
|
208
|
+
A wrapper to add external function
|
|
209
|
+
Wrap the f(X, ...) into f(X, ...) + ext_func(X, ...)
|
|
210
|
+
|
|
211
|
+
And the wrapped func_args would be the concatenation of `func_args` and `ext_func_args`.
|
|
212
|
+
Hence, the number of func_args, i.e., the `n_func_args` is required to determine that
|
|
213
|
+
the first `n_func_args`-th args belong to `func` and the rest belong to `ext_func`
|
|
214
|
+
|
|
215
|
+
Keyword Args is similar, that require the keys of `func_kwargs`, and the rest belongs to `ext_func`.
|
|
216
|
+
|
|
217
|
+
`grad_func` is so, too.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
func: the original function
|
|
221
|
+
ext_func: the external adding function
|
|
222
|
+
n_func_args: number of args that belongs to `func`
|
|
223
|
+
k_func_kwargs: keywords list that belongs to `func`
|
|
224
|
+
n_grad_func_args,
|
|
225
|
+
k_grad_func_kwargs
|
|
226
|
+
|
|
227
|
+
Methods:
|
|
228
|
+
Energy: input Tensor `X` and PygData `graph`, it will update graph.pos into X and return model(graph)['energy'].
|
|
229
|
+
Grad: input Tensor `X` and PygData `graph`, it will update graph.pos into X and return model(graph)['forces'].
|
|
230
|
+
|
|
231
|
+
"""
|
|
232
|
+
self._model = func
|
|
233
|
+
self._ext_func = ext_func
|
|
234
|
+
self._grad_func = grad_func
|
|
235
|
+
self._ext_grad_func = ext_grad_func
|
|
236
|
+
self.n_func_args = n_func_args
|
|
237
|
+
self.k_func_kwargs = set(k_func_kwargs) if k_func_kwargs is not None else set()
|
|
238
|
+
self.n_grad_func_args = n_grad_func_args
|
|
239
|
+
self.k_grad_func_kwargs = set(k_grad_func_kwargs) if k_grad_func_kwargs is not None else set()
|
|
240
|
+
|
|
241
|
+
self.forces = None
|
|
242
|
+
|
|
243
|
+
@staticmethod
|
|
244
|
+
def _auto_grad_func(X: th.Tensor, y: th.Tensor | None = None):
|
|
245
|
+
grad_shape = th.ones_like(y)
|
|
246
|
+
g = th.autograd.grad(y, X, grad_shape)
|
|
247
|
+
return g[0]
|
|
248
|
+
|
|
249
|
+
def Energy(self, X, *func_args, **func_kwargs, ):
|
|
250
|
+
self.X = X
|
|
251
|
+
true_func_args = func_args[:self.n_func_args]
|
|
252
|
+
ext_func_args = func_args[self.n_func_args:]
|
|
253
|
+
true_func_kwargs = {k:func_kwargs[k] for k in (func_kwargs.keys() & self.k_func_kwargs)}
|
|
254
|
+
ext_func_kwargs = {k:func_kwargs[k] for k in (func_kwargs.keys() - self.k_func_kwargs)}
|
|
255
|
+
|
|
256
|
+
self.y = self._model(self.X, *true_func_args, **true_func_kwargs) + self._ext_func(X, *ext_func_args, **ext_func_kwargs)
|
|
257
|
+
|
|
258
|
+
return self.y
|
|
259
|
+
|
|
260
|
+
def Grad(self, X, *grad_func_args, **grad_func_kwargs,):
|
|
261
|
+
true_func_args = grad_func_args[:self.n_func_args]
|
|
262
|
+
ext_func_args = grad_func_args[self.n_func_args:]
|
|
263
|
+
true_func_kwargs = {k: grad_func_kwargs[k] for k in (grad_func_kwargs.keys() & self.k_func_kwargs)}
|
|
264
|
+
ext_func_kwargs = {k: grad_func_kwargs[k] for k in (grad_func_kwargs.keys() - self.k_func_kwargs)}
|
|
265
|
+
g = self._grad_func(X, *true_func_args, **true_func_kwargs) + self._ext_grad_func(X, *ext_func_args, **ext_func_kwargs)
|
|
266
|
+
|
|
267
|
+
return g
|
|
268
|
+
|
|
269
|
+
def Grad_y(self, X, y, *grad_func_args, **grad_func_kwargs, ):
|
|
270
|
+
true_func_args = grad_func_args[:self.n_func_args]
|
|
271
|
+
ext_func_args = grad_func_args[self.n_func_args:]
|
|
272
|
+
true_func_kwargs = {k: grad_func_kwargs[k] for k in (grad_func_kwargs.keys() & self.k_func_kwargs)}
|
|
273
|
+
ext_func_kwargs = {k: grad_func_kwargs[k] for k in (grad_func_kwargs.keys() - self.k_func_kwargs)}
|
|
274
|
+
g = self._grad_func(X, y, *true_func_args, **true_func_kwargs) + self._ext_grad_func(X, y, *ext_func_args, **ext_func_kwargs)
|
|
275
|
+
|
|
276
|
+
return g
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
""" Micro canonical ensemble (NVE) Molecular Dynamics via Verlet algo. """
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2024-2025.7.4, BUCToolkit.
|
|
4
|
+
# Authors: Pu Pengxin, Song Xin
|
|
5
|
+
# Version: 0.9a
|
|
6
|
+
# File: NVE.py
|
|
7
|
+
# Environment: Python 3.12
|
|
8
|
+
|
|
9
|
+
# ruff: noqa: E701, E702, E703
|
|
10
|
+
from typing import Iterable, Dict, Any, List, Literal, Optional, Callable, Sequence, Tuple # noqa: F401
|
|
11
|
+
|
|
12
|
+
import torch as th
|
|
13
|
+
|
|
14
|
+
from ._BaseMD import _BaseMD
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class NVE(_BaseMD):
|
|
18
|
+
"""
|
|
19
|
+
Micro canonical ensemble (NVE) molecular dynamics implemented via velocity Verlet algo.
|
|
20
|
+
|
|
21
|
+
Parameters:
|
|
22
|
+
time_step: float, time per step (fs).
|
|
23
|
+
max_step: int, maximum steps.
|
|
24
|
+
T_init: float, initial temperature, only to generate initial velocities of atoms by Maxwell-Boltzmann distribution. If V_init is given, T_init will be ignored.
|
|
25
|
+
output_structures_per_step: int, output structures per output_structures_per_step steps.
|
|
26
|
+
device: str|torch.device, device that program rum on.
|
|
27
|
+
verbose: int, control the detailed degree of output information. 0 for silence, 1 for output Energy and Forces per step, 2 for output all structures.
|
|
28
|
+
is_compile: whether to use jit to compile integrator or not.
|
|
29
|
+
compile_kwargs: keyword arguments passed to compile. Only work when is_compile is True.
|
|
30
|
+
|
|
31
|
+
Methods:
|
|
32
|
+
run: run BatchMD.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
time_step: float,
|
|
39
|
+
max_step: int,
|
|
40
|
+
T_init: float = 298.15,
|
|
41
|
+
output_file: str | None = None,
|
|
42
|
+
output_structures_per_step: int = 1,
|
|
43
|
+
device: str | th.device = 'cpu',
|
|
44
|
+
verbose: int = 0,
|
|
45
|
+
is_compile: bool = False,
|
|
46
|
+
compile_kwargs: dict | None = None,
|
|
47
|
+
):
|
|
48
|
+
super().__init__(
|
|
49
|
+
time_step,
|
|
50
|
+
max_step,
|
|
51
|
+
T_init,
|
|
52
|
+
output_file,
|
|
53
|
+
output_structures_per_step,
|
|
54
|
+
device,
|
|
55
|
+
verbose,
|
|
56
|
+
is_compile,
|
|
57
|
+
compile_kwargs
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def _updateXV(
|
|
61
|
+
self, X, V, Force,
|
|
62
|
+
func, grad_func_, func_args, func_kwargs, grad_func_args, grad_func_kwargs,
|
|
63
|
+
masses, atom_masks, is_grad_func_contain_y, batch_indices,
|
|
64
|
+
) -> Tuple[th.Tensor, th.Tensor, th.Tensor, th.Tensor]:
|
|
65
|
+
""" Update X, V, Force, and return X, V, Energy, Force. """
|
|
66
|
+
#X: th.Tensor = X.contiguous()
|
|
67
|
+
#V: th.Tensor = V.contiguous()
|
|
68
|
+
#masses: th.Tensor = masses.contiguous()
|
|
69
|
+
with th.no_grad():
|
|
70
|
+
# X = X + V * self.time_step + (Force / (2. * masses)) * self.time_step ** 2 * 9.64853329045427e-3
|
|
71
|
+
V.addcdiv_(Force, masses, value=0.5 * self.time_step * 9.64853329045427e-3)
|
|
72
|
+
X.add_(V, alpha=self.time_step)
|
|
73
|
+
# V = V + (Force / (2. * masses)) * self.time_step * 9.64853329045427e-3 # half-step veloc. update, to avoid saving 2 Forces Tensors.
|
|
74
|
+
# Update V
|
|
75
|
+
Energy, Force = self._calc_EF(
|
|
76
|
+
X,
|
|
77
|
+
func,
|
|
78
|
+
func_args,
|
|
79
|
+
func_kwargs,
|
|
80
|
+
grad_func_,
|
|
81
|
+
grad_func_args,
|
|
82
|
+
grad_func_kwargs,
|
|
83
|
+
is_grad_func_contain_y
|
|
84
|
+
)
|
|
85
|
+
Force.mul_(atom_masks)
|
|
86
|
+
|
|
87
|
+
# V = V + (Force / (2. * masses)) * self.time_step * 9.64853329045427e-3
|
|
88
|
+
V.addcdiv_(Force, masses, value=0.5 * self.time_step * 9.64853329045427e-3)
|
|
89
|
+
|
|
90
|
+
return X, V, Energy, Force
|
|
91
|
+
|
|
92
|
+
return X, V, Energy, Force
|