Skip to content

Commit 0425db5

Browse files
committed
all local changes
1 parent 68f63db commit 0425db5

File tree

7 files changed

+1465
-0
lines changed

7 files changed

+1465
-0
lines changed

atomate/qchem/firetasks/.ipynb_checkpoints/__init__-checkpoint.py

Whitespace-only changes.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import json
2+
import os
3+
4+
from fireworks import FiretaskBase, FWAction, explicit_serialize
5+
from fireworks.utilities.fw_serializers import DATETIME_HANDLER
6+
7+
from atomate.common.firetasks.glue_tasks import get_calc_loc
8+
from atomate.qchem.database import QChemCalcDb
9+
from atomate.qchem.drones import QChemDrone
10+
from atomate.utils.utils import env_chk, get_logger
11+
12+
__author__ = "Samuel Blau"
13+
__copyright__ = "Copyright 2018, The Materials Project"
14+
__version__ = "0.1"
15+
__maintainer__ = "Samuel Blau"
16+
__email__ = "[email protected]"
17+
__status__ = "Alpha"
18+
__date__ = "4/25/18"
19+
__credits__ = "Brandon Wood, Shyam Dwaraknath, Xiaohui Qu"
20+
21+
logger = get_logger(__name__)
22+
23+
24+
@explicit_serialize
25+
class QChemToDb(FiretaskBase):
26+
"""
27+
Enter a QChem run into the database. Uses current directory unless you
28+
specify calc_dir or calc_loc.
29+
30+
Optional params:
31+
calc_dir (str): path to dir (on current filesystem) that contains QChem
32+
input and output files. Default: use current working directory.
33+
calc_loc (str OR bool): if True will set most recent calc_loc. If str
34+
search for the most recent calc_loc with the matching name
35+
input_file (str): name of the QChem input file
36+
output_file (str): name of the QChem output file
37+
additional_fields (dict): dict of additional fields to add
38+
db_file (str): path to file containing the database credentials.
39+
Supports env_chk. Default: write data to JSON file.
40+
fw_spec_field (str): if set, will update the task doc with the contents
41+
of this key in the fw_spec.
42+
multirun (bool): Whether the job to parse includes multiple
43+
calculations in one input / output pair.
44+
runs (list): Series of file suffixes that the Drone should look for
45+
when parsing output.
46+
"""
47+
48+
optional_params = [
49+
"calc_dir",
50+
"calc_loc",
51+
"input_file",
52+
"output_file",
53+
"additional_fields",
54+
"db_file",
55+
"fw_spec_field",
56+
"multirun",
57+
"runs",
58+
]
59+
60+
def run_task(self, fw_spec):
61+
# get the directory that contains the QChem dir to parse
62+
calc_dir = os.getcwd()
63+
if "calc_dir" in self:
64+
calc_dir = self["calc_dir"]
65+
elif self.get("calc_loc"):
66+
calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"]
67+
input_file = self.get("input_file", "mol.qin")
68+
output_file = self.get("output_file", "mol.qout")
69+
multirun = self.get("multirun", False)
70+
runs = self.get("runs", None)
71+
72+
# parse the QChem directory
73+
logger.info(f"PARSING DIRECTORY: {calc_dir}")
74+
75+
additional_fields = self.get("additional_fields", {})
76+
77+
drone = QChemDrone(runs=runs, additional_fields=additional_fields)
78+
79+
# assimilate (i.e., parse)
80+
task_doc = drone.assimilate(
81+
path=calc_dir,
82+
input_file=input_file,
83+
output_file=output_file,
84+
multirun=multirun,
85+
)
86+
87+
# Check for additional keys to set based on the fw_spec
88+
if self.get("fw_spec_field"):
89+
task_doc.update(
90+
{self.get("fw_spec_field"): fw_spec.get(self.get("fw_spec_field"))}
91+
)
92+
93+
# Update fw_spec with final/optimized structure
94+
update_spec = {}
95+
if task_doc.get("output").get("optimized_molecule"):
96+
update_spec["prev_calc_molecule"] = task_doc["output"]["optimized_molecule"]
97+
update_spec["prev_calc_mulliken"] = task_doc["output"]["mulliken"]
98+
if "RESP" in task_doc["output"]:
99+
update_spec["prev_calc_resp"] = task_doc["output"]["RESP"]
100+
elif "ESP" in task_doc["output"]:
101+
update_spec["prev_calc_esp"] = task_doc["output"]["ESP"]
102+
103+
# get the database connection
104+
db_file = env_chk(self.get("db_file"), fw_spec)
105+
106+
# db insertion or taskdoc dump
107+
if not db_file:
108+
with open(os.path.join(calc_dir, "task.json"), "w") as f:
109+
f.write(json.dumps(task_doc, default=DATETIME_HANDLER))
110+
else:
111+
mmdb = QChemCalcDb.from_db_file(db_file, admin=True)
112+
t_id = mmdb.insert(task_doc)
113+
logger.info(f"Finished parsing with task_id: {t_id}")
114+
115+
return FWAction(
116+
stored_data={"task_id": task_doc.get("task_id", None)},
117+
update_spec=update_spec,
118+
)
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# This module defines firetasks for writing QChem input files
2+
3+
import os
4+
5+
from fireworks import FiretaskBase, explicit_serialize
6+
from pymatgen.analysis.graphs import MoleculeGraph
7+
from pymatgen.analysis.local_env import OpenBabelNN
8+
from pymatgen.io.qchem.inputs import QCInput
9+
10+
from atomate.utils.utils import load_class
11+
12+
__author__ = "Brandon Wood"
13+
__copyright__ = "Copyright 2018, The Materials Project"
14+
__version__ = "0.1"
15+
__maintainer__ = "Brandon Wood"
16+
__email__ = "[email protected]"
17+
__status__ = "Alpha"
18+
__date__ = "5/20/18"
19+
__credits__ = "Sam Blau, Shyam Dwaraknath"
20+
21+
22+
@explicit_serialize
23+
class WriteInputFromIOSet(FiretaskBase):
24+
"""
25+
Writes QChem Input files from input sets. A dictionary is passed to WriteInputFromIOSet where
26+
parameters are given as keys in the dictionary.
27+
28+
required_params:
29+
qc_input_set (QChemDictSet or str): Either a QChemDictSet object or a string
30+
name for the QChem input set (e.g., "OptSet"). *** Note that if the molecule is to be inherited through
31+
fw_spec qc_input_set must be a string name for the QChem input set. ***
32+
33+
optional_params:
34+
molecule (Molecule): Molecule that will be subjected to an electronic structure calculation
35+
qchem_input_params (dict): When using a string name for QChem input set, use this as a dict
36+
to specify kwargs for instantiating the input set parameters. This setting is
37+
ignored if you provide the full object representation of a QChemDictSet. Basic uses
38+
would be to modify the default inputs of the set, such as dft_rung, basis_set,
39+
pcm_dielectric, scf_algorithm, or max_scf_cycles. See pymatgen/io/qchem/sets.py for
40+
default values of all input parameters. For instance, if a user wanted to use a
41+
more advanced DFT functional, include a pcm with a dielectric of 30, and use a
42+
larger basis, the user would set qchem_input_params = {"dft_rung": 5,
43+
"pcm_dielectric": 30, "basis_set": "6-311++g**"}. However, more advanced
44+
customization of the input is also possible through the overwrite_inputs key which
45+
allows the user to directly modify the rem, pcm, smd, and solvent dictionaries that
46+
QChemDictSet passes to inputs.py to print an actual input file. For instance, if a
47+
user wanted to set the sym_ignore flag in the rem section of the input file to
48+
true, then they would set qchem_input_params = {"overwrite_inputs": "rem":
49+
{"sym_ignore": "true"}}. Of course, overwrite_inputs could be used in conjunction
50+
with more typical modifications, as seen in the test_double_FF_opt workflow test.
51+
input_file (str): Name of the QChem input file. Defaults to mol.qin
52+
write_to_dir (str): Path of the directory where the QChem input file will be written,
53+
the default is to write to the current working directory
54+
"""
55+
56+
required_params = ["qchem_input_set"]
57+
optional_params = ["molecule", "qchem_input_params", "input_file", "write_to_dir"]
58+
59+
def run_task(self, fw_spec):
60+
input_file = os.path.join(
61+
self.get("write_to_dir", ""), self.get("input_file", "mol.qin")
62+
)
63+
64+
# if a full QChemDictSet object was provided
65+
if hasattr(self["qchem_input_set"], "write_file"):
66+
qcin = self["qchem_input_set"]
67+
# if a molecule is being passed through fw_spec
68+
elif fw_spec.get("prev_calc_molecule"):
69+
prev_calc_mol = fw_spec.get("prev_calc_molecule")
70+
# if a molecule is also passed as an optional parameter
71+
if self.get("molecule"):
72+
mol = self.get("molecule")
73+
# check if mol and prev_calc_mol are isomorphic
74+
mol_graph = MoleculeGraph.with_local_env_strategy(mol, OpenBabelNN())
75+
prev_mol_graph = MoleculeGraph.with_local_env_strategy(
76+
prev_calc_mol, OpenBabelNN()
77+
)
78+
# If they are isomorphic, aka a previous FW has not changed bonding,
79+
# then we will use prev_calc_mol. If bonding has changed, we will use mol.
80+
if mol_graph.isomorphic_to(prev_mol_graph):
81+
mol = prev_calc_mol
82+
elif self["qchem_input_set"] != "OptSet":
83+
print(
84+
"WARNING: Molecule from spec is not isomorphic to passed molecule!"
85+
)
86+
mol = prev_calc_mol
87+
else:
88+
print(
89+
"Not using prev_calc_mol as it is not isomorphic to passed molecule!"
90+
)
91+
else:
92+
mol = prev_calc_mol
93+
94+
qcin_cls = load_class("pymatgen.io.qchem.sets", self["qchem_input_set"])
95+
qcin = qcin_cls(mol, **self.get("qchem_input_params", {}))
96+
# if a molecule is only included as an optional parameter
97+
elif self.get("molecule"):
98+
qcin_cls = load_class("pymatgen.io.qchem.sets", self["qchem_input_set"])
99+
qcin = qcin_cls(self.get("molecule"), **self.get("qchem_input_params", {}))
100+
# if no molecule is present raise an error
101+
else:
102+
raise KeyError(
103+
"No molecule present, add as an optional param or check fw_spec"
104+
)
105+
qcin.write(input_file)
106+
107+
108+
@explicit_serialize
109+
class WriteCustomInput(FiretaskBase):
110+
"""
111+
Writes QChem Input files from custom input sets. This firetask gives the maximum flexibility when trying
112+
to define custom input parameters.
113+
114+
required_params:
115+
qchem_input_custom (dict): Define custom input parameters to generate a qchem input file.
116+
This should be a dictionary of dictionaries (i.e. {{"rem": {"method": "b3lyp", basis": "6-31*G++", ...}
117+
Each QChem section should be a key with its own dictionary as the value. For more details on how
118+
the input should be structured look at pymatgen.io.qchem.inputs
119+
*** ***
120+
121+
optional_params:
122+
input_file (str): Name of the QChem input file. Defaults to mol.qin
123+
write_to_dir (str): Path of the directory where the QChem input file will be written,
124+
the default is to write to the current working directory
125+
"""
126+
127+
required_params = ["rem"]
128+
# optional_params will need to be modified if more QChem sections are added QCInput
129+
optional_params = [
130+
"molecule",
131+
"opt",
132+
"pcm",
133+
"solvent",
134+
"van_der_waals",
135+
"input_file",
136+
"write_to_dir",
137+
]
138+
139+
def run_task(self, fw_spec):
140+
input_file = os.path.join(
141+
self.get("write_to_dir", ""), self.get("input_file", "mol.qin")
142+
)
143+
# if a molecule is being passed through fw_spec
144+
if fw_spec.get("prev_calc_molecule"):
145+
prev_calc_mol = fw_spec.get("prev_calc_molecule")
146+
# if a molecule is also passed as an optional parameter
147+
if self.get("molecule"):
148+
mol = self.get("molecule")
149+
# check if mol and prev_calc_mol are isomorphic
150+
mol_graph = MoleculeGraph.with_local_env_strategy(mol, OpenBabelNN())
151+
prev_mol_graph = MoleculeGraph.with_local_env_strategy(
152+
prev_calc_mol, OpenBabelNN()
153+
)
154+
if mol_graph.isomorphic_to(prev_mol_graph):
155+
mol = prev_calc_mol
156+
else:
157+
print(
158+
"WARNING: Molecule from spec is not isomorphic to passed molecule!"
159+
)
160+
else:
161+
mol = prev_calc_mol
162+
elif self.get("molecule"):
163+
mol = self.get("molecule")
164+
else:
165+
raise KeyError(
166+
"No molecule present, add as an optional param or check fw_spec"
167+
)
168+
# in the current structure there needs to be a statement for every optional QChem section
169+
# the code below defaults the section to None if the variable is not passed
170+
opt = self.get("opt", None)
171+
pcm = self.get("pcm", None)
172+
solvent = self.get("solvent", None)
173+
vdw_mode = self.get("vdw_mode", "atomic")
174+
van_der_waals = self.get("van_der_waals", None)
175+
176+
qcin = QCInput(
177+
molecule=mol,
178+
rem=self["rem"],
179+
opt=opt,
180+
pcm=pcm,
181+
solvent=solvent,
182+
van_der_waals=van_der_waals,
183+
vdw_mode=vdw_mode,
184+
)
185+
qcin.write_file(input_file)
186+
187+
188+
@explicit_serialize
189+
class WriteInput(FiretaskBase):
190+
"""
191+
Writes QChem input file from QCInput object.
192+
193+
required_params:
194+
qc_input (QCInput): QCInput object
195+
196+
optional_params:
197+
input_file (str): Name of the QChem input file. Defaults to mol.qin
198+
write_to_dir (str): Path of the directory where the QChem input file will be written,
199+
the default is to write to the current working directory
200+
201+
"""
202+
203+
required_params = ["qc_input"]
204+
optional_params = ["input_file", "write_to_dir"]
205+
206+
def run_task(self, fw_spec):
207+
# if a QCInput object is provided
208+
input_file = os.path.join(
209+
self.get("write_to_dir", ""), self.get("input_file", "mol.qin")
210+
)
211+
212+
qcin = self["qc_input"]
213+
qcin.write_file(input_file)

0 commit comments

Comments
 (0)