-
Notifications
You must be signed in to change notification settings - Fork 1
/
energy_force.py
75 lines (65 loc) · 3.68 KB
/
energy_force.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# -*- coding: utf-8 -*-
"""
Computing Energy and Force Using Models Inside Model Zoo
========================================================
TorchANI has a model zoo trained by NeuroChem. These models are shipped with
TorchANI and can be used directly.
"""
###############################################################################
# To begin with, let's first import the modules we will use:
import torch
import torchani
###############################################################################
# Let's now manually specify the device we want TorchANI to run:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
###############################################################################
# Let's now load the built-in ANI-1ccx models. The builtin ANI-1ccx contains 8
# models trained with diffrent initialization. Predicting the energy and force
# using the average of the 8 models outperform using a single model, so it is
# always recommended to use an ensemble, unless the speed of computation is an
# issue in your application.
#
# The ``periodic_table_index`` arguments tells TorchANI to use element index
# in periodic table to index species. If not specified, you need to use
# 0, 1, 2, 3, ... to index species
model = torchani.models.ANI2x(periodic_table_index=True).to(device)
###############################################################################
# Now let's define the coordinate and species. If you just want to compute the
# energy and force for a single structure like in this example, you need to
# make the coordinate tensor has shape ``(1, Na, 3)`` and species has shape
# ``(1, Na)``, where ``Na`` is the number of atoms in the molecule, the
# preceding ``1`` in the shape is here to support batch processing like in
# training. If you have ``N`` different structures to compute, then make it
# ``N``.
#
# .. note:: The coordinates are in Angstrom, and the energies you get are in Hartree
coordinates = torch.tensor([[[0.03192167, 0.00638559, 0.01301679],
[-0.83140486, 0.39370209, -0.26395324],
[-0.66518241, -0.84461308, 0.20759389],
[0.45554739, 0.54289633, 0.81170881],
[0.66091919, -0.16799635, -0.91037834]]],
requires_grad=True, device=device)
# In periodic table, C = 6 and H = 1
species = torch.tensor([[6, 1, 1, 1, 1]], device=device)
###############################################################################
# Now let's compute energy and force:
energy = model((species, coordinates)).energies
derivative = torch.autograd.grad(energy.sum(), coordinates)[0]
force = -derivative
###############################################################################
# And print to see the result:
print('Energy:', energy.item())
print('Force:', force.squeeze())
###############################################################################
# you can also get the atomic energies (WARNING: these have no physical
# meaning) by calling:
_, atomic_energies = model.atomic_energies((species, coordinates))
###############################################################################
# this gives you the average (shifted) energies over all models of the ensemble by default,
# with the same shape as the coordinates. Dummy atoms, if present, will have an
# energy of zero
print('Average Atomic energies, for species 6 1 1 1 1', atomic_energies)
###############################################################################
# you can also access model specific atomic energies
_, atomic_energies = model.atomic_energies((species, coordinates), average=False)
print('Atomic energies of first model, for species 6 1 1 1 1', atomic_energies[0, :, :])