-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from mir-group/develop
Version 0.3.0
- Loading branch information
Showing
25 changed files
with
584 additions
and
123 deletions.
There are no files selected for viewing
This file contains 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,3 +1,4 @@ | ||
md_runs/ | ||
simon_configs/ | ||
.idea/ | ||
.vscode/ | ||
|
This file contains 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 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 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 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 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 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 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
Empty file.
This file contains 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,72 @@ | ||
from typing import Union | ||
import torch | ||
|
||
from ase.calculators.calculator import Calculator, all_changes | ||
|
||
from nequip.data import AtomicData, AtomicDataDict | ||
import nequip.scripts.deploy | ||
|
||
|
||
class NequIPCalculator(Calculator): | ||
"""NequIP ASE Calculator.""" | ||
|
||
implemented_properties = ["energy", "forces"] | ||
|
||
def __init__( | ||
self, | ||
model: torch.jit.ScriptModule, | ||
r_max: float, | ||
device: Union[str, torch.device], | ||
energy_units_to_eV: float = 1.0, | ||
length_units_to_A: float = 1.0, | ||
**kwargs | ||
): | ||
Calculator.__init__(self, **kwargs) | ||
self.results = {} | ||
self.model = model | ||
self.r_max = r_max | ||
self.device = device | ||
self.energy_units_to_eV = energy_units_to_eV | ||
self.length_units_to_A = length_units_to_A | ||
|
||
@classmethod | ||
def from_deployed_model( | ||
cls, model_path, device: Union[str, torch.device] = "cpu", **kwargs | ||
): | ||
# load model | ||
model, metadata = nequip.scripts.deploy.load_deployed_model( | ||
model_path=model_path, device=device | ||
) | ||
r_max = float(metadata[nequip.scripts.deploy.R_MAX_KEY]) | ||
|
||
# build nequip calculator | ||
return cls(model=model, r_max=r_max, device=device, **kwargs) | ||
|
||
def calculate(self, atoms=None, properties=["energy"], system_changes=all_changes): | ||
""" | ||
Calculate properties. | ||
:param atoms: ase.Atoms object | ||
:param properties: [str], properties to be computed, used by ASE internally | ||
:param system_changes: [str], system changes since last calculation, used by ASE internally | ||
:return: | ||
""" | ||
# call to base-class to set atoms attribute | ||
Calculator.calculate(self, atoms) | ||
|
||
# prepare data | ||
data = AtomicData.from_ase(atoms=atoms, r_max=self.r_max) | ||
|
||
data = data.to(self.device) | ||
|
||
# predict + extract data | ||
out = self.model(AtomicData.to_AtomicDataDict(data)) | ||
forces = out[AtomicDataDict.FORCE_KEY].detach().cpu().numpy() | ||
energy = out[AtomicDataDict.TOTAL_ENERGY_KEY].detach().cpu().item() | ||
|
||
# store results | ||
self.results = { | ||
"energy": energy * self.energy_units_to_eV, | ||
# force has units eng / len: | ||
"forces": forces * (self.energy_units_to_eV / self.length_units_to_A), | ||
} |
This file contains 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,115 @@ | ||
""" Custom Nose-Hoover NVT thermostat based on ASE. | ||
This code was originally written by Jonathan Mailoa based on these notes: | ||
https://www2.ph.ed.ac.uk/~dmarendu/MVP/MVP03.pdf | ||
It was then adapted by Simon Batzner to be used within ASE. Parts of the overall outline of the class are also based on the Langevin class in ASE. | ||
""" | ||
|
||
import numpy as np | ||
|
||
from ase.md.md import MolecularDynamics | ||
from ase.md.velocitydistribution import Stationary, ZeroRotation | ||
from ase import units | ||
|
||
|
||
class NoseHoover(MolecularDynamics): | ||
"""Nose-Hoover (constant N, V, T) molecular dynamics. | ||
Usage: NoseHoover(atoms, dt, temperature) | ||
atoms | ||
The list of atoms. | ||
timestep | ||
The time step. | ||
temperature | ||
Target temperature of the MD run in [K] | ||
nvt_q | ||
Q in the Nose-Hoover equations | ||
Example Usage: | ||
nvt_dyn = NoseHoover( | ||
atoms=atoms, | ||
timestep=0.5 * units.fs, | ||
temperature=300., | ||
nvt_q=334. | ||
) | ||
""" | ||
|
||
def __init__( | ||
self, | ||
atoms, | ||
timestep, | ||
temperature, | ||
nvt_q, | ||
trajectory=None, | ||
logfile=None, | ||
loginterval=1, | ||
append_trajectory=False, | ||
): | ||
# set angular and com momentum to zero, necessary for nose-hoover dynamics. | ||
ZeroRotation(atoms) | ||
Stationary(atoms) | ||
|
||
# thermostat parameters | ||
self.temp = temperature | ||
self.nvt_q = nvt_q | ||
self.dt = timestep | ||
self.dtdt = np.power(self.dt, 2) | ||
self.nvt_bath = 0.0 | ||
|
||
self.natoms = len(atoms) | ||
|
||
MolecularDynamics.__init__( | ||
self, | ||
atoms, | ||
timestep, | ||
trajectory, | ||
logfile, | ||
loginterval, | ||
append_trajectory=append_trajectory, | ||
) | ||
|
||
def step(self): | ||
"""Perform a MD step.""" | ||
masses = self.atoms.get_masses() | ||
|
||
modified_acc = ( | ||
self.atoms.get_forces() / masses[:, np.newaxis] | ||
- self.nvt_bath * self.atoms.get_velocities() | ||
) | ||
pos_fullstep = ( | ||
self.atoms.get_positions() | ||
+ self.dt * self.atoms.get_velocities() | ||
+ 0.5 * self.dtdt * modified_acc | ||
) | ||
vel_halfstep = self.atoms.get_velocities() + 0.5 * self.dt * modified_acc | ||
|
||
self.atoms.set_positions(pos_fullstep) | ||
|
||
e_kin_diff = 0.5 * ( | ||
np.sum(masses * np.sum(self.atoms.get_velocities() ** 2, axis=1)) | ||
- (3 * self.natoms + 1) * units.kB * self.temp | ||
) | ||
|
||
nvt_bath_halfstep = self.nvt_bath + 0.5 * self.dt * e_kin_diff / self.nvt_q | ||
e_kin_diff_halfstep = 0.5 * ( | ||
np.sum(masses * np.sum(vel_halfstep ** 2, axis=1)) | ||
- (3 * self.natoms + 1) * units.kB * self.temp | ||
) | ||
self.nvt_bath = ( | ||
nvt_bath_halfstep + 0.5 * self.dt * e_kin_diff_halfstep / self.nvt_q | ||
) | ||
self.atoms.set_velocities( | ||
( | ||
vel_halfstep | ||
+ 0.5 * self.dt * (self.atoms.get_forces() / masses[:, np.newaxis]) | ||
) | ||
/ (1 + 0.5 * self.dt * self.nvt_bath) | ||
) |
This file contains 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.