Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ASE tutorial #43

Merged
merged 66 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
3ea3e6a
Add gradient calculator
frostedoyster Jan 4, 2024
79d161e
Fix linter
frostedoyster Jan 4, 2024
e65679d
Loss draft
frostedoyster Jan 11, 2024
8591d7d
Add tests for losses
frostedoyster Jan 11, 2024
8df7e41
Wrap forces and stresses
frostedoyster Jan 11, 2024
0ffc0a9
Clarify cell convention
frostedoyster Jan 11, 2024
9253931
Merge branch 'main' into forces-virials
frostedoyster Jan 11, 2024
9b93eaa
Support multiple model outputs, use new loss
frostedoyster Jan 11, 2024
83c94e6
Fix composition calculator
frostedoyster Jan 11, 2024
4f1c569
Address review
frostedoyster Jan 12, 2024
7c32d9e
Partial draft
frostedoyster Jan 12, 2024
3081a0f
Finished trainer
frostedoyster Jan 12, 2024
ed8697f
Make linter happy
frostedoyster Jan 12, 2024
589b586
Merge branch 'main' into finalize-training
frostedoyster Jan 13, 2024
01a528b
Fix small merge issue
frostedoyster Jan 12, 2024
aa31433
Add new functions to the documentation
frostedoyster Jan 16, 2024
9061f1c
Add tutorial how to override arch params
PicoCentauri Jan 18, 2024
631d274
Adapt to most recent parser changes
frostedoyster Jan 19, 2024
dc523b7
Train with actual train/validation splits
frostedoyster Jan 19, 2024
fe0bd01
Fix some small issues
frostedoyster Jan 19, 2024
f579652
Merge branch 'arch_override_docs' into finalize-training
frostedoyster Jan 20, 2024
2e82d22
Fix docs build?
frostedoyster Jan 19, 2024
3f9c927
Attempt to export
frostedoyster Jan 20, 2024
0142784
Address reviewer comments
frostedoyster Jan 23, 2024
bc60b87
Merge branch 'main' into finalize-training
frostedoyster Jan 23, 2024
6590939
Merge branch 'finalize-training' into export
frostedoyster Jan 23, 2024
236e5a3
Make SOAP-BPNN model saveable
frostedoyster Jan 26, 2024
addd65d
Hack better
frostedoyster Jan 26, 2024
a7811bc
Update `MANIFEST.in`
frostedoyster Jan 26, 2024
f8b2325
Update tests and docs
frostedoyster Jan 26, 2024
ecb8279
Add some comments on the hacks
frostedoyster Jan 26, 2024
27e3bc9
Fix `usage.sh`?
frostedoyster Jan 26, 2024
5fb18c1
Add ASE tutorial
frostedoyster Jan 26, 2024
374b88b
Fix docs?
frostedoyster Jan 26, 2024
3acf607
Fix docs??
frostedoyster Jan 26, 2024
e7397ac
Merge branch 'main' into export
frostedoyster Jan 26, 2024
c34f85c
Fix merge bug
frostedoyster Jan 26, 2024
84a64b5
Try to put a notebook together
frostedoyster Jan 28, 2024
2e004e5
Run correct NVE MD
frostedoyster Jan 28, 2024
199f98a
Also fix units in `metatensor.torch.atomistic`
frostedoyster Jan 31, 2024
b88e586
Turn example into python script
frostedoyster Jan 31, 2024
ed62a5f
Sphinx gallery?
frostedoyster Jan 31, 2024
82f1c22
Sphinx gallery??
frostedoyster Jan 31, 2024
19f77cb
Fix conf.py
frostedoyster Jan 31, 2024
ef9e532
Make README.rst a title
frostedoyster Jan 31, 2024
bf891b4
Title?
frostedoyster Jan 31, 2024
793488b
Added sphinx config
PicoCentauri Jan 31, 2024
54fbe61
Some improvments to the tutorial
PicoCentauri Jan 31, 2024
e7d240b
Try to run gallery as a subprocess of conf.py
frostedoyster Jan 31, 2024
cf069fb
Merge branch 'main' into export
frostedoyster Feb 1, 2024
1623ae1
Retrain model, add symlink
frostedoyster Feb 1, 2024
9dc2a78
Add info about model
PicoCentauri Feb 1, 2024
b02a0eb
Use vanilla sphinx-gallery
PicoCentauri Feb 1, 2024
ecea35f
More details to the tutorial
PicoCentauri Feb 1, 2024
eb54ddf
fix some typos
PicoCentauri Feb 1, 2024
04af489
Merge branch 'export' into ase-tutorial
frostedoyster Feb 1, 2024
12d0c7a
fix wrong title
PicoCentauri Feb 1, 2024
6e5df56
Merge branch 'ase-tutorial' of https://github.com/lab-cosmo/metatenso…
frostedoyster Feb 1, 2024
9fe6305
Fix leftover issue from merge
frostedoyster Feb 2, 2024
4699030
Linter betrayal AGAIN
frostedoyster Feb 2, 2024
cc939da
Run example on the fly
PicoCentauri Feb 2, 2024
629f90d
reorder example files
PicoCentauri Feb 2, 2024
c8e4bb4
finish restructure
PicoCentauri Feb 2, 2024
33214f2
remove output file
PicoCentauri Feb 2, 2024
4a22182
Merge branch 'main' into ase-tutorial
frostedoyster Feb 2, 2024
c22ee68
fix docs
PicoCentauri Feb 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,10 @@ cython_debug/

# model output directories
outputs/
examples/*.xyz
examples/basic_usage/*.xyz
!docs/static/*.pt
!examples/ase/*.pt

# sphinx gallery
docs/src/examples
*execution_times*
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ graft src
include LICENSE
include README.md

# TODO: remove once the hack is not needed anymore
include scripts/hotfix_metatensor.py

prune docs
Expand Down
2 changes: 2 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
ase
furo
sphinx >= 7
sphinx-gallery
sphinx-toggleprompt
tomli
12 changes: 8 additions & 4 deletions docs/src/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
ROOT = os.path.abspath(os.path.join("..", ".."))
sys.path.insert(0, ROOT)

# when importing metatensor-torch, this will change the definition of the classes
# to include the documentation
os.environ["METATENSOR_IMPORT_FOR_SPHINX"] = "1"

# -- Project information -----------------------------------------------------

# The master toctree document.
Expand Down Expand Up @@ -41,8 +37,16 @@
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx_toggleprompt",
"sphinx_gallery.gen_gallery",
]

sphinx_gallery_conf = {
"filename_pattern": "/*",
"examples_dirs": ["../../examples"],
"gallery_dirs": ["examples"],
"min_reported_time": 5,
}

python_use_unqualified_type_names = True

autoclass_content = "both"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/getting-started/override.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Override Architecture's Default Parameters
In our initial tutorial, we used default parameters to train a model employing the
SOAP-BPNN architecture, as shown in the following config:

.. literalinclude:: ../../static/options.yaml
.. literalinclude:: ../../static/qm9/options.yaml
:language: yaml

While default parameters often serve as a good starting point, depending on your
Expand Down
17 changes: 10 additions & 7 deletions docs/src/getting-started/usage.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _label_basic_usage:

Basic Usage
===========

Expand All @@ -11,7 +13,7 @@ general help of `metatensor-models` can be accessed using
We now demonstrate how to `train` and `evaluate` a model from the command line. For this
example we use the :ref:`architecture-soap-bpnn` architecture and a subset of the `QM9
dataset <https://paperswithcode.com/dataset/qm9>`_. You can obtain the reduced dataset
from our :download:`website <../../static/qm9_reduced_100.xyz>`.
from our :download:`website <../../static/qm9/qm9_reduced_100.xyz>`.

Training
########
Expand Down Expand Up @@ -39,7 +41,7 @@ The default model and training hyperparameter for each model are listed in their
corresponding documentation page. We will use these minimal options to run an example
training using the default hyperparameters of an SOAP BPNN model

.. literalinclude:: ../../static/options.yaml
.. literalinclude:: ../../static/qm9/options.yaml
:language: yaml

For each training run a new output directory in the format
Expand All @@ -50,7 +52,7 @@ default, this output directory is used to store Hydra's output for the run
behavior in the options file. To start the training create an ``options.yaml`` file in
the current directory and type

.. literalinclude:: ../../../examples/usage.sh
.. literalinclude:: ../../../examples/basic_usage/usage.sh
:language: bash
:lines: 3-8

Expand All @@ -64,22 +66,23 @@ The sub-command to evaluate an already trained model is

metatensor-models eval

.. literalinclude:: ../../../examples/usage.sh
.. literalinclude:: ../../../examples/basic_usage/usage.sh
:language: bash
:lines: 9-25


Exporting
#########

Exporting a model required if you want to use it in other frameworks, especially in
molecular dynamics simulations. The sub-command to export a model is
Exporting a model is very useful if you want to use it in other frameworks,
especially in molecular dynamics simulations.
The sub-command to export an already trained model is

.. code-block:: bash

metatensor-models export

.. literalinclude:: ../../../examples/usage.sh
.. literalinclude:: ../../../examples/basic_usage/usage.sh
:language: bash
:lines: 25-

Expand Down
1 change: 1 addition & 0 deletions docs/src/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ This is a collection of atomistic models interfaced with ``metatensor``.
:hidden:

getting-started/index
tutorials/index
architectures/index
dev-docs/index
10 changes: 10 additions & 0 deletions docs/src/tutorials/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Tutorials
=========

This sections includes some more advanced tutorials on the usage of the
``metatensor-models`` package.

.. toctree::
:maxdepth: 1

../examples/ase/run_ase
1,100 changes: 1,100 additions & 0 deletions docs/static/ethanol/ethanol_reduced_100.xyz

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions docs/static/ethanol/options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defaults:
- architecture: soap_bpnn # architecture used to train the model
- _self_

architecture:
training:
batch_size: 16
num_epochs: 100
learning_rate: 0.01

# Section defining the parameters for structure and target data
training_set:
structures: "ethanol_reduced_100.xyz"
targets:
energy:
key: "energy"
unit: "kcal/mol" # very important to run simulations

validation_set: 0.1
test_set: 0.0
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions examples/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
metatensor-models Examples
==========================

This folder consists of introductory and advanced examples.
2 changes: 2 additions & 0 deletions examples/ase/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Running molecular dynamics with ASE
===================================
1 change: 1 addition & 0 deletions examples/ase/ethanol_reduced_100.xyz
Binary file added examples/ase/exported-model.pt
Binary file not shown.
1 change: 1 addition & 0 deletions examples/ase/options.yaml
214 changes: 214 additions & 0 deletions examples/ase/run_ase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
"""
Running molecular dynamics with ASE
===================================

This tutorial demonstrates how to use an already trained and exported model to run an
ASE simulation of a single ethanol molecule in vacuum. We use a model that was trained
using the :ref:`architecture-soap-bpnn` architecture on 100 ethanol structures
containing energies and forces. You can obtain the :download:`dataset file
<../../../static/ethanol/ethanol_reduced_100.xyz>` used in this example from our
website. The dataset is a subset of the `rMD17 dataset
<https://iopscience.iop.org/article/10.1088/2632-2153/abba6f/meta>`_.

The model was trained using the following training options.

.. literalinclude:: ../../../static/ethanol/options.yaml
:language: yaml

You can train and export the model yourself using the following commands

.. literalinclude:: ../../../../examples/ase/train_export.sh
:language: bash

A detailed step-by-step introduction on how to train and export a model is provided in
the :ref:`label_basic_usage` tutorial.
"""

# %%
#
# First, we start by importing the necessary libraries, including the integration of ASE
# calculators for metatensor atomistic models


import ase.md
import ase.md.velocitydistribution
import ase.units
import ase.visualize.plot
import matplotlib.pyplot as plt
import numpy as np
import rascaline.torch # noqa
from ase.geometry.analysis import Analysis
from metatensor.torch.atomistic.ase_calculator import MetatensorCalculator


# %%
#
# .. note::
# We have to import ``rascaline.torch`` even though it is not used explicitly in this
# tutorial. The SOAP-BPNN model contains compiled extensions and therefore the import
# is required.
#
# Setting up the simulation
# -------------------------
#
# Next, we initialize the simulation by extracting the initial positions from the
# dataset file which we initially trained the model on.

training_frames = ase.io.read("ethanol_reduced_100.xyz", ":")
atoms = training_frames[0].copy()

# %%
#
# Below we show the initial configuration of a single ethanol molecule in vacuum.

ase.visualize.plot.plot_atoms(atoms)

plt.xlabel("Å")
plt.ylabel("Å")

plt.show()


# %%
#
# Our initial coordinates do not include velocities. We initialize the velocities
# according to a Maxwell-Boltzmann Distribution at 300 K.

ase.md.velocitydistribution.MaxwellBoltzmannDistribution(atoms, temperature_K=300)

# %%
#
# We now register our exported model as the energy calculator to obtain energies and
# forces.

atoms.calc = MetatensorCalculator("exported-model.pt")

# %%
#
# Finally, we define the integrator which we use to obtain new positions and velocities
# based on our energy calculator. We use a common timestep of 0.5 fs.

integrator = ase.md.VelocityVerlet(atoms, timestep=0.5 * ase.units.fs)


# %%
#
# Run the simulation
# ------------------
#
# We now have everything ready to run the MD simulation at constant energy (NVE). To
# keep the execution time of this tutorial small we run the simulations only for 100
# steps. If you want to run a longer simulation you can increase the ``n_steps``
# variable.
#
# During the simulation loop we collect data about the simulation for later analysis.


n_steps = 100

potential_energy = np.zeros(n_steps)
kinetic_energy = np.zeros(n_steps)
total_energy = np.zeros(n_steps)
trajectory = []

for step in range(n_steps):
# run a single simulation step
integrator.run(1)

trajectory.append(atoms.copy())
potential_energy[step] = atoms.get_potential_energy()
kinetic_energy[step] = atoms.get_kinetic_energy()
total_energy[step] = atoms.get_total_energy()

# %%
#
# Analyse the results
# -------------------
#
# Energy conservation
# ###################
#
# For a first analysis, we plot the evolution of the mean of the kinetic, potential, and
# total energy which is an important measure for the stability of a simulation.
#
# As shown below we see that both the kinetic, potential, and total energy
# fluctuate but the total energy is conserved over the length of the simulation.


plt.plot(potential_energy - potential_energy.mean(), label="potential energy")
plt.plot(kinetic_energy - kinetic_energy.mean(), label="kinetic energy")
plt.plot(total_energy - total_energy.mean(), label="total energy")

plt.xlabel("step")
plt.ylabel("energy / kcal/mol")
plt.legend()

plt.show()

# %%
#
# Inspect the final structure
# ###########################
#
# Even though the total energy is conserved, we also have to verify that the ethanol
# molecule is stable and the bonds did not break.

ase.visualize.plot.plot_atoms(trajectory[-1])
plt.xlabel("Å")
plt.ylabel("Å")

plt.show()

# %%
#
# Carbon-hydrogen radial distribution function
# ############################################
#
# As a final analysis we also calculate and plot the carbon-hydrogen radial distribution
# function (RDF) from the trajectory and compare this to the RDF from the training set.
#
# To use the RDF code from ase we first have to define a unit cell for our structures.
# We choose a cubic one with a side length of 10 Å.

for atoms in training_frames:
atoms.cell = 10 * np.ones(3)
atoms.pbc = True

for atoms in trajectory:
atoms.cell = 10 * np.ones(3)
atoms.pbc = True

# %%
#
# We now can initilize the :py:class:`ase.geometry.analysis.Analysis` objects and
# compute the the RDF using the :py:meth:`ase.geometry.analysis.Analysis.get_rdf`
# method.

ana_traj = Analysis(trajectory)
ana_train = Analysis(training_frames)

rdf_traj = ana_traj.get_rdf(rmax=5, nbins=50, elements=["C", "H"], return_dists=True)
rdf_train = ana_train.get_rdf(rmax=5, nbins=50, elements=["C", "H"], return_dists=True)

# %%
#
# We extract the bin positions from the returned values and and averege the RDF over the
# whole trajectory and dataset, respectively.

bins = rdf_traj[0][1]
rdf_traj_mean = np.mean([rdf_traj[i][0] for i in range(n_steps)], axis=0)
rdf_train_mean = np.mean([rdf_train[i][0] for i in range(n_steps)], axis=0)

# %%
#
# Plotting the RDF verifies that the hydrogen bonds are stable, confirming that we
# performed an energy-conserving and stable simulation.

plt.plot(bins, rdf_traj_mean, label="trajectory")
plt.plot(bins, rdf_train_mean, label="training set")

plt.legend()
plt.xlabel("r / Å")
plt.ylabel("radial distribution function")

plt.show()
Loading
Loading