Skip to content

Commit

Permalink
Adds a adapt+NEB+TS method (duartegroup#172)
Browse files Browse the repository at this point in the history
* Allow partition with max delta

* Adaptive initial force constant

* Add adapt+NEB+TS method

* Add tests

* Add assert when no path

* Update changelog
  • Loading branch information
t-young31 committed Oct 1, 2022
1 parent c70b858 commit a4ac4df
Show file tree
Hide file tree
Showing 40 changed files with 707 additions and 658 deletions.
4 changes: 2 additions & 2 deletions autode/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ class ORCA:

optts_block = ('\n%geom\n'
'Calc_Hess true\n'
'Recalc_Hess 30\n'
'Recalc_Hess 20\n'
'Trust -0.1\n'
'MaxIter 150\n'
'MaxIter 100\n'
'end')

keywords = KeywordsSet(
Expand Down
6 changes: 3 additions & 3 deletions autode/hessians.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from autode.log import logger
from autode.config import Config
from autode.constants import Constants
from autode.values import ValueArray, Frequency, Coordinates
from autode.values import ValueArray, Frequency, Coordinates, Distance
from autode.utils import work_in, hashable
from autode.units import (Unit, wavenumber,
ha_per_ang_sq, ha_per_a0_sq, J_per_m_sq, J_per_ang_sq,
Expand Down Expand Up @@ -362,10 +362,10 @@ class NumericalHessianCalculator:

def __init__(self,
species: 'autode.species.Species',
method: 'autode.wrappers.base.Method',
method: 'autode.wrappers.methods.Method',
keywords: 'autode.wrappers.keywords.GradientKeywords',
do_c_diff: bool,
shift: 'autode.values.Distance',
shift: Distance,
n_cores: Optional[int] = None
):

Expand Down
77 changes: 70 additions & 7 deletions autode/input_output.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import os
from typing import Collection

from typing import Collection, List, Optional
from autode.atoms import Atom, Atoms
from autode.exceptions import XYZfileDidNotExist
from autode.exceptions import XYZfileWrongFormat
from autode.log import logger
from autode.utils import StringDict


def xyz_file_to_atoms(filename: str) -> Atoms:
Expand All @@ -19,14 +21,9 @@ def xyz_file_to_atoms(filename: str) -> Atoms:
"""
logger.info(f'Getting atoms from {filename}')

_check_xyz_file_exists(filename)
atoms = Atoms()

if not os.path.exists(filename):
raise XYZfileDidNotExist(f'{filename} did not exist')

if not filename.endswith('.xyz'):
raise XYZfileWrongFormat('xyz file must have a .xyz file extension')

with open(filename, 'r') as xyz_file:

try:
Expand Down Expand Up @@ -85,3 +82,69 @@ def atoms_to_xyz_file(atoms: Collection[Atom],
print(f'{atom.label:<3}{x:10.5f}{y:10.5f}{z:10.5f}',
file=xyz_file)
return None


def xyz_file_to_molecules(filename: str) -> List["autode.Molecule"]:
"""
From a .xyz file containing potentially more than a single molecule
return a list of molecules from it.
---------------------------------------------------------------------------
Arguments:
filename: Filename to open
Returns:
(list(autode.species.molecule.Molecule)): Molecules
"""
from autode.species.molecule import Molecule # prevents circular imports

_check_xyz_file_exists(filename)

lines = open(filename, "r").readlines()
n_atoms = int(lines[0].split()[0])
molecules = []

for i in range(0, len(lines), n_atoms + 2):

atoms = []
title_line = StringDict(lines[i + 1])
for j, line in enumerate(lines[i + 2:i + n_atoms + 2]):
symbol, x, y, z = line.split()[:4]
atoms.append(Atom(atomic_symbol=symbol, x=x, y=y, z=z))

molecule = Molecule(atoms=atoms,
solvent_name=title_line.get("solvent", None))

_set_attr_from_title_line(molecule, "charge", title_line)
_set_attr_from_title_line(molecule, "mult", title_line)
_set_attr_from_title_line(molecule, "energy", title_line, "E")

molecules.append(molecule)

return molecules


def _check_xyz_file_exists(filename: str) -> None:

if not os.path.exists(filename):
raise XYZfileDidNotExist(f'{filename} did not exist')

if not filename.endswith('.xyz'):
raise XYZfileWrongFormat('xyz file must have a .xyz file extension')

return None


def _set_attr_from_title_line(species: "Species",
attr: str,
title_line: StringDict,
key_in_line: Optional[str] = None) -> None:

if key_in_line is None:
key_in_line = attr # Default to e.g. charge attribute is "charge = 0"
try:
setattr(species, attr, title_line[key_in_line])
except IndexError:
logger.warning(f"Failed to set the species {attr} from xyz file")

return None
8 changes: 4 additions & 4 deletions autode/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def get_hmethod() -> "autode.wrappers.methods.Method":
---------------------------------------------------------------------------
Returns:
(autode.wrappers.base.ElectronicStructureMethod): High-level method
(autode.wrappers.methods.Method): High-level method
"""

h_methods = [ORCA(), G09(), NWChem(), G16(), QChem()]
Expand All @@ -79,7 +79,7 @@ def get_lmethod() -> "autode.wrappers.methods.Method":
"""Get the 'low-level' electronic structure theory method to use
Returns:
(autode.wrappers.base.ElectronicStructureMethod): Low-level method
(autode.wrappers.methods.Method): Low-level method
"""

all_methods = [XTB(), MOPAC(), ORCA(), G16(), G09(), NWChem(), QChem()]
Expand All @@ -100,7 +100,7 @@ def get_first_available_method(possibilities) -> "autode.wrappers.methods.Method
possibilities (list(autode.wrappers.base.ElectronicStructureMethod)):
Returns:
(autode.wrappers.base.ElectronicStructureMethod): Method
(autode.wrappers.methods.Method): Method
Raises:
(autode.exceptions.MethodUnavailable):
Expand All @@ -123,7 +123,7 @@ def get_defined_method(name, possibilities) -> "autode.wrappers.methods.Method":
possibilities (list(autode.wrappers.base.ElectronicStructureMethod)):
Returns:
(autode.wrappers.base.ElectronicStructureMethod): Method
(autode.wrappers.methods.Method): Method
Raises:
(autode.exceptions.MethodUnavailable):
Expand Down
20 changes: 12 additions & 8 deletions autode/neb/ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
https://doi.org/10.1063/1.1329672
"""
import numpy as np
from typing import Optional
from autode.neb.original import NEB, Images, Image
from autode.log import logger

Expand Down Expand Up @@ -39,7 +40,11 @@ def get_force(self, im_l, im_r) -> np.ndarray:

class CImages(Images):

def __init__(self, images, wait_iterations=4):
def __init__(self,
images: Images,
num: int = None,
wait_iterations: int = 4,
init_k: Optional[float] = None):
"""
Initialise a set of images
Expand All @@ -49,8 +54,11 @@ def __init__(self, images, wait_iterations=4):
wait_iterations (int): Number of iterations to wait before turning
on the climbing image
init_k: Initial force constant
"""
super().__init__(num=len(images), init_k=images[0].k)
super().__init__(num=num if num is not None else len(images),
init_k=init_k if init_k is not None else images[0].k)

self.wait_iteration = wait_iterations
for i, image in enumerate(images):
Expand Down Expand Up @@ -83,6 +91,8 @@ def increment(self) -> None:

class CINEB(NEB):

_images_type = CImages

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

Expand All @@ -104,9 +114,3 @@ def _minimise(self, method, n_cores, etol, max_n=30
result = super()._minimise(method, n_cores, etol, max_n)

return result

def partition(self, n: int) -> None:
"""Partition a set of CI images"""
super().partition(n=n)
self.images = CImages(self.images)
return None
4 changes: 2 additions & 2 deletions autode/neb/neb.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

def get_ts_guess_neb(reactant: 'autode.species.Species',
product: 'autode.species.Species',
method: 'autode.wrappers.base.Method',
method: 'autode.wrappers.methods.Method',
name: str = 'neb',
n: int = 10):
"""
Expand All @@ -23,7 +23,7 @@ def get_ts_guess_neb(reactant: 'autode.species.Species',
product (autode.species.Species):
method (autode.wrappers.base.Method):
method (autode.wrappers.methods.Method):
name (str):
Expand Down
Loading

0 comments on commit a4ac4df

Please sign in to comment.