-
Notifications
You must be signed in to change notification settings - Fork 18
i-PI integration #307
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
Merged
i-PI integration #307
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
bb424fa
Added a stub of an i-PI interface
ceriottm d1ae923
Update initialization and storing of I-PI interface class
max-veit 0ebe0b1
Partial implementation of i-PI compute function
max-veit 02cf947
Add virial output in the format i-PI expects
max-veit ebcf075
IT'S ALIIIIIIVE
max-veit 5bc3ffa
Flip virial sign convention to match i-PI's
max-veit 1dd6f41
Add driver script
Lgigli2190 79e4557
Rename i-PI driver so it's clear what it drives
max-veit 0ef0e8c
Add i-Pi example
Lgigli2190 1a898e1
Make i-PI calculator into a generic ML-MD interface
max-veit 3a6852a
Remove old, unused i-PI driver scripts
max-veit cf0e660
Make dependency on tqdm optional
max-veit 68d6cad
Reorganize docs and make a place to discuss i-PI interface
max-veit c1329c5
Expand doc on MD interfaces
max-veit 547c922
Add simple GAP model (and source data and params) for tests
max-veit 0df18fc
Make generic MD read only the first structure of a given template file
max-veit 7390c79
Add annotations (with basic units) to gap model output file
max-veit 737708f
Add tests for GenericMDCalculator
max-veit d4479cc
Document extra utilities in krr.py
max-veit 384ae15
Add Zundel i-PI example to online docs
max-veit d2fd3a9
Update version requirements for compiling docs
max-veit 9027d9e
Rename models/IP*.py to shorter, more Pythonic module names
max-veit 02e2323
Overhaul initialization of generic MD calculator
max-veit 264972a
Remove unneeded serialization of generic MD driver
max-veit 9b529e3
Update KRR utils doc
max-veit 3281e07
Add tests for new GenericMD initialization
max-veit 8a074b3
Update example notebook, remove tqdm dependency from bindings
max-veit 6a9f4bd
Force docutils version to avoid bug in 0.17
max-veit File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
from .krr import train_gap_model, KRR | ||
from .krr import train_gap_model, KRR, compute_KNM | ||
from .kernels import Kernel |
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
"""Generic calculator-style interface for MD""" | ||
import ase.io | ||
import numpy as np | ||
|
||
from ..utils import BaseIO, load_obj | ||
from ..neighbourlist.structure_manager import AtomsList, unpack_ase | ||
|
||
|
||
class GenericMDCalculator: | ||
|
||
"""Generic MD driver for a librascal model | ||
|
||
Initialize with model JSON and a structure template, and calculate | ||
energies and forces based on position/cell updates _assuming the | ||
order and identity of atoms does not change_. | ||
""" | ||
|
||
matrix_indices_in_voigt_notation = ( | ||
(0, 0), | ||
(1, 1), | ||
(2, 2), | ||
(1, 2), | ||
(0, 2), | ||
(0, 1), | ||
) | ||
|
||
def __init__( | ||
self, model_json, is_periodic, structure_template=None, atomic_numbers=None | ||
): | ||
"""Initialize a model and structure template | ||
|
||
Parameters | ||
---------- | ||
model_json Filename for a JSON file defining the potential | ||
is_periodic Specify whether the simulation is periodic or not | ||
This helps avoid confusion if a geometry's "periodic" | ||
flags have been set improperly, which can happen e.g. | ||
if ASE cannot read the cell information in a file. If | ||
using a structure template and this is set to True, | ||
will raise an error unless at least one of the PBC | ||
flags in the structure template is on. If set to | ||
False, will raise an error if all PBC flags are not | ||
off. Set to None to skip PBC checking. If not using a | ||
structure template, this setting will determine the PBC | ||
flags of the created atomic structure. | ||
structure_template | ||
Filename for an ASE-compatible Atoms object, used | ||
only to initialize atom types and numbers | ||
atomic_numbers | ||
List of atom types (atomic numbers) to initialize | ||
the atomic structure in case no structure template | ||
is given | ||
""" | ||
super(GenericMDCalculator, self).__init__() | ||
self.model_filename = model_json | ||
self.model = load_obj(model_json) | ||
self.representation = self.model.get_representation_calculator() | ||
self.manager = None | ||
# Structure initialization | ||
self.is_periodic = is_periodic | ||
if structure_template is not None: | ||
self.template_filename = structure_template | ||
self.atoms = ase.io.read(structure_template, 0) | ||
if (is_periodic is not None) and ( | ||
is_periodic != np.any(self.atoms.get_pbc()) | ||
): | ||
raise ValueError( | ||
"Structure template PBC flags: " | ||
+ str(self.atoms.get_pbc()) | ||
+ " incompatible with 'is_periodic' setting" | ||
) | ||
elif atomic_numbers is not None: | ||
self.atoms = ase.Atoms(numbers=atomic_numbers, pbc=is_periodic) | ||
else: | ||
raise ValueError( | ||
"Must specify one of 'structure_template' or 'atomic_numbers'" | ||
) | ||
|
||
def calculate(self, positions, cell_matrix): | ||
"""Calculate energies and forces from position/cell update | ||
|
||
positions Atomic positions (Nx3 matrix) | ||
cell_matrix Unit cell (in ASE format, cell vectors as rows) | ||
(set to zero for non-periodic simulations) | ||
|
||
The units of positions and cell are determined by the model JSON | ||
file; for now, only Å is supported. Energies, forces, and | ||
stresses are returned in the same units (eV and Å supported). | ||
max-veit marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Returns a tuple of energy, forces, and stress - forces are | ||
returned as an Nx3 array and stresses are returned as a 3x3 array | ||
|
||
Stress convention: The stresses have units eV/Å^3 | ||
(volume-normalized) and are defined as the gradients of the | ||
energy with respect to the cell parameters. | ||
""" | ||
# Quick consistency checks | ||
if positions.shape != (len(self.atoms), 3): | ||
raise ValueError( | ||
"Improper shape of positions (is the number of atoms consistent?)" | ||
) | ||
if cell_matrix.shape != (3, 3): | ||
raise ValueError("Improper shape of cell info (expected 3x3 matrix)") | ||
|
||
# Update ASE Atoms object (we only use ASE to handle any | ||
# re-wrapping of the atoms that needs to take place) | ||
self.atoms.set_cell(cell_matrix) | ||
self.atoms.set_positions(positions) | ||
|
||
# Convert from ASE to librascal | ||
if self.manager is None: | ||
# happens at the begining of the MD run | ||
at = self.atoms.copy() | ||
at.wrap(eps=1e-11) | ||
self.manager = [at] | ||
elif isinstance(self.manager, AtomsList): | ||
structure = unpack_ase(self.atoms, wrap_pos=True) | ||
structure.pop("center_atoms_mask") | ||
self.manager[0].update(**structure) | ||
|
||
# Compute representations and evaluate model | ||
self.manager = self.representation.transform(self.manager) | ||
energy = self.model.predict(self.manager) | ||
forces = self.model.predict_forces(self.manager) | ||
stress_voigt = self.model.predict_stress(self.manager) | ||
stress_matrix = np.zeros((3, 3)) | ||
stress_matrix[tuple(zip(*self.matrix_indices_in_voigt_notation))] = stress_voigt | ||
# Symmetrize the stress matrix (replicate upper-diagonal entries) | ||
stress_matrix += np.triu(stress_matrix).T | ||
return energy, forces, stress_matrix |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.