-
Notifications
You must be signed in to change notification settings - Fork 874
/
Copy pathinputs.py
97 lines (85 loc) · 3.51 KB
/
inputs.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""Classes for writing XTB input files."""
from __future__ import annotations
import logging
import os
from typing import TYPE_CHECKING
from monty.json import MSONable
if TYPE_CHECKING:
from pymatgen.core import Molecule
__author__ = "Alex Epstein"
__copyright__ = "Copyright 2020, The Materials Project"
__version__ = "0.1"
__maintainer__ = "Alex Epstein"
__email__ = "[email protected]"
__credits__ = "Sam Blau, Evan Spotte-Smith"
logger = logging.getLogger(__name__)
class CRESTInput(MSONable):
"""
An object representing CREST input files.
Because CREST is controlled through command line flags and external
files, the CRESTInput class mainly consists of methods for containing
and writing external files.
"""
def __init__(
self,
molecule: Molecule,
working_dir: str = ".",
coords_filename: str | None = "crest_in.xyz",
constraints: dict[str, list[int] | float] | None = None,
):
"""
Args:
molecule (Molecule): Molecule object
working_dir (str): Directory to write input files to
coords_filename (str): Name of input coordinates file
constraints (dict): Dictionary of common editable parameters for
.constrains file. {"atoms": [List of 1-indexed atoms to fix],
"force_constant": float].
"""
self.molecule = molecule
self.coords_filename = coords_filename
self.constraints = constraints
self.working_dir = working_dir
def write_input_files(self):
"""Write input files to working directory."""
self.molecule.to(filename=os.path.join(self.working_dir, self.coords_filename))
if self.constraints:
constrains_string = self.constrains_template(
molecule=self.molecule,
reference_fnm=self.coords_filename,
constraints=self.constraints,
)
with open(".constrains", mode="w") as file:
file.write(constrains_string)
@staticmethod
def constrains_template(molecule, reference_fnm, constraints) -> str:
"""
Args:
molecule (Molecule): Molecule the constraints will be performed on
reference_fnm (str): Name of file containing reference structure in same directory
constraints (dict): Dictionary of common editable parameters for .constrains file.
{"atoms": [List of 1-indexed atoms to fix], "force_constant": float].
Returns:
str: for .constrains file
"""
atoms_to_constrain = constraints["atoms"]
force_constant = constraints["force_constant"]
mol = molecule
atoms_for_mtd = [idx for idx in range(1, len(mol) + 1) if idx not in atoms_to_constrain]
# Write as 1-3,5 instead of 1,2,3,5
interval_list = [atoms_for_mtd[0]]
for idx, val in enumerate(atoms_for_mtd):
if val + 1 not in atoms_for_mtd:
interval_list.append(val)
if idx != len(atoms_for_mtd) - 1:
interval_list.append(atoms_for_mtd[idx + 1])
allowed_mtd_string = ",".join(
[f"{interval_list[i]}-{interval_list[i + 1]}" for i in range(len(interval_list)) if i % 2 == 0]
)
return (
"$constrain\n"
f" atoms: {','.join(map(str, atoms_to_constrain))}\n"
f" force constant={force_constant}\n"
f" reference={reference_fnm}\n$metadyn\n"
f" atoms: {allowed_mtd_string}\n$end"
)