Skip to content
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

Minor Q-Chem updates #292

Merged
merged 15 commits into from
Sep 21, 2023
27 changes: 20 additions & 7 deletions custodian/qchem/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def correct(self):
# Try forcing a new initial guess at each iteration
elif (
self.qcinp.rem.get("scf_guess_always", "none").lower() != "true"
and len(self.outdata.get("energy_trajectory", [])) > 0
and "molecule_from_last_geometry" in self.outdata
):
self.qcinp.rem["scf_guess_always"] = "true"
actions.append({"scf_guess_always": "true"})
Expand All @@ -130,7 +130,7 @@ def correct(self):
"maxiter"
] = self.geom_max_cycles
actions.append({"geom_max_cycles:": self.geom_max_cycles})
if len(self.outdata.get("energy_trajectory")) > 1:
if "molecule_from_last_geometry" in self.outdata:
self.qcinp.molecule = self.outdata.get("molecule_from_last_geometry")
actions.append({"molecule": "molecule_from_last_geometry"})

Expand Down Expand Up @@ -164,7 +164,7 @@ def correct(self):
if self.qcinp.rem.get("thresh", "10") != "14":
self.qcinp.rem["thresh"] = "14"
actions.append({"thresh": "14"})
elif len(self.outdata.get("energy_trajectory")) > 1:
elif "molecule_from_last_geometry" in self.outdata:
self.qcinp.molecule = self.outdata.get("molecule_from_last_geometry")
actions.append({"molecule": "molecule_from_last_geometry"})
if self.qcinp.rem.get("scf_algorithm", "diis").lower() == "diis":
Expand All @@ -183,7 +183,7 @@ def correct(self):
if self.qcinp.rem.get("thresh", "10") != "14":
self.qcinp.rem["thresh"] = "14"
actions.append({"thresh": "14"})
elif len(self.outdata.get("energy_trajectory")) > 1:
elif "molecule_from_last_geometry" in self.outdata:
self.qcinp.molecule = self.outdata.get("molecule_from_last_geometry")
actions.append({"molecule": "molecule_from_last_geometry"})

Expand All @@ -198,9 +198,15 @@ def correct(self):
"coordinates"
] = "delocalized"
actions.append({"coordinates": "delocalized"})
if self.qcinp.geom_opt.get("initial_hessian", "none") != "read":
self.qcinp.geom_opt["initial_hessian"] = "model"
actions.append({"initial_hessian": "model"})
elif self.qcinp.geom_opt["coordinates"] == "delocalized":
self.qcinp.geom_opt["coordinates"] = "cartesian" # pylint: disable=unsupported-assignment-operation
actions.append({"coordinates": "cartesian"})
if self.qcinp.geom_opt.get("initial_hessian", "none") == "model":
del self.qcinp.geom_opt["initial_hessian"]
actions.append({"initial_hessian": "deleted"})

elif "premature_end_FileMan_error" in self.errors:
# Given defaults, the first two handlers will typically be skipped.
Expand All @@ -210,13 +216,13 @@ def correct(self):
if self.qcinp.rem.get("thresh", "10") != "14":
self.qcinp.rem["thresh"] = "14"
actions.append({"thresh": "14"})
elif self.qcinp.rem.get("job_type") == "opt" or "optimization":
elif self.qcinp.rem.get("job_type") == "opt" or self.qcinp.rem.get("job_type") == "optimization":
if self.qcinp.rem.get("scf_guess_always", "none").lower() != "true":
self.qcinp.rem["scf_guess_always"] = "true"
actions.append({"scf_guess_always": "true"})
else:
print("Don't know how to fix a FileMan error for an opt while always generating a new SCF guess!")
elif self.qcinp.rem.get("job_type") == "freq" or "frequency":
elif self.qcinp.rem.get("job_type") == "freq" or self.qcinp.rem.get("job_type") == "frequency":
self.qcinp.rem["cpscf_nseg"] = str(self.outdata["cpscf_nseg"] + 1)
actions.append({"cpscf_nseg": str(self.outdata["cpscf_nseg"] + 1)})

Expand Down Expand Up @@ -321,6 +327,13 @@ def correct(self):
self.qcinp.rem["cpscf_nseg"] = str(self.outdata["cpscf_nseg"] + 1)
actions.append({"cpscf_nseg": str(self.outdata["cpscf_nseg"] + 1)})

elif "gdm_neg_precon_error" in self.errors:
if "molecule_from_last_geometry" in self.outdata:
self.qcinp.molecule = self.outdata.get("molecule_from_last_geometry")
actions.append({"molecule": "molecule_from_last_geometry"})
else:
print("Not sure how to fix gdm_neg_precon_error on the first SCF!")

elif "mem_static_too_small" in self.errors:
# mem_static should never exceed 2000 MB according to the Q-Chem manual
self.qcinp.rem["mem_static"] = "2000"
Expand Down Expand Up @@ -374,7 +387,7 @@ def correct(self):
and "initial_hessian" in self.qcinp.geom_opt
) and str(self.qcinp.geom_opt["initial_hessian"]).lower() == "read":
del self.qcinp.geom_opt["initial_hessian"]
actions.append({"geom_opt.initial_hessian-read": "deleted"})
actions.append({"initial_hessian": "deleted"})
os.rename(self.input_file, self.input_file + ".last")
self.qcinp.write_file(self.input_file)
return {"errors": self.errors, "warnings": self.warnings, "actions": actions}
5 changes: 4 additions & 1 deletion custodian/qchem/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def setup(self):
def postprocess(self):
"""Renames and removes scratch files after running QChem."""
scratch_dir = os.path.join(os.environ["QCSCRATCH"], "scratch")
for file in ["HESS", "GRAD", "plots/dens.0.cube"]:
for file in ["HESS", "GRAD", "plots/dens.0.cube", "131.0", "53.0", "132.0"]:
file_path = os.path.join(scratch_dir, file)
if os.path.exists(file_path):
shutil.copy(file_path, os.getcwd())
Expand Down Expand Up @@ -161,6 +161,9 @@ def run(self):
if os.path.exists(os.path.join(os.environ["QCSCRATCH"], "132.0")):
os.mkdir(local_scratch)
shutil.move(os.path.join(os.environ["QCSCRATCH"], "132.0"), local_scratch)
if os.path.exists(os.path.join(os.environ["QCSCRATCH"], "53.0")):
os.mkdir(local_scratch, exist_ok=True)
shutil.move(os.path.join(os.environ["QCSCRATCH"], "53.0"), local_scratch)
with open(self.qclog_file, "w") as qclog:
return subprocess.Popen(self.current_command, stdout=qclog, shell=True) # pylint: disable=R1732

Expand Down
30 changes: 30 additions & 0 deletions custodian/qchem/tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,36 @@ def test_OOS_read_hess(self):
]
self._check_equivalent_inputs(os.path.join(test_dir, "OOS_read_hess_next.qin"), "mol.qin")

def test_gdm_neg_precon_error(self):
shutil.copyfile(
os.path.join(test_dir, "gdm_neg_precon_error.qin.gz"),
os.path.join(scr_dir, "mol.qin.gz"),
)
shutil.copyfile(
os.path.join(test_dir, "gdm_neg_precon_error.qout.gz"),
os.path.join(scr_dir, "mol.qout.gz"),
)
h = QChemErrorHandler(input_file="mol.qin", output_file="mol.qout")
h.check()
d = h.correct()
assert d["errors"] == ["gdm_neg_precon_error"]
assert d["actions"] == [{"molecule": "molecule_from_last_geometry"}]

def test_fileman_cpscf_nseg_error(self):
shutil.copyfile(
os.path.join(test_dir, "fileman_cpscf.qin.gz"),
os.path.join(scr_dir, "mol.qin.gz"),
)
shutil.copyfile(
os.path.join(test_dir, "fileman_cpscf.qout.gz"),
os.path.join(scr_dir, "mol.qout.gz"),
)
h = QChemErrorHandler(input_file="mol.qin", output_file="mol.qout")
h.check()
d = h.correct()
assert d["errors"] == ["premature_end_FileMan_error"]
assert d["actions"] == [{"cpscf_nseg": "3"}]

def tearDown(self):
os.chdir(cwd)
shutil.rmtree(scr_dir)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.