Example #1
0
 def _test_property(self, key):
     for file in single_job_out_names:
         self.assertEqual(QCOutput(os.path.join(test_dir, file)).data.get(key), single_job_dict[file].get(key))
     for file in multi_job_out_names:
         outputs = QCOutput.multiple_outputs_from_file(QCOutput, os.path.join(test_dir, file), keep_sub_files=False)
         for i, sub_output in enumerate(outputs):
             self.assertEqual(sub_output.data.get(key), multi_job_dict[file][i].get(key))
Example #2
0
 def process_qchem_multirun(dir_name, input_files, output_files):
     """
     Process a QChem run which is known to include multiple calculations
     in a single input/output pair.
     """
     if len(input_files) != 1:
         raise ValueError(
             "ERROR: The drone can only process a directory containing a single input/output pair when each include multiple calculations."
         )
     else:
         for key in input_files:
             to_return = []
             qchem_input_file = os.path.join(dir_name, input_files.get(key))
             qchem_output_file = os.path.join(dir_name,
                                              output_files.get(key))
             multi_out = QCOutput.multiple_outputs_from_file(
                 QCOutput, qchem_output_file, keep_sub_files=False)
             multi_in = QCInput.from_multi_jobs_file(qchem_input_file)
             for ii, out in enumerate(multi_out):
                 d = out.data
                 d["input"] = {}
                 d["input"]["molecule"] = multi_in[ii].molecule
                 d["input"]["rem"] = multi_in[ii].rem
                 d["input"]["opt"] = multi_in[ii].opt
                 d["input"]["pcm"] = multi_in[ii].pcm
                 d["input"]["solvent"] = multi_in[ii].solvent
                 d["task"] = {"type": key, "name": "calc" + str(ii)}
                 to_return.append(d)
         return to_return
Example #3
0
 def generate_single_job_dict():
     """
     Used to generate test dictionary for single jobs
     """
     single_job_dict = {}
     for file in single_job_out_names:
         single_job_dict[file] = QCOutput(os.path.join(test_dir, file)).data
     dumpfn(single_job_dict, "single_job.json")
Example #4
0
 def test_RunQChemFake(self):
     os.chdir(os.path.join(module_dir, "..", "fake_run"))
     firetask = RunQChemFake(ref_dir=os.path.join(module_dir, "..", "..",
                                                  "test_files", "real_run"))
     firetask.run_task(fw_spec={})
     ref_out = QCOutput(
         os.path.join(module_dir, "..", "..", "test_files", "real_run",
                      "mol.qout")).data
     this_out = QCOutput("mol.qout").data
     for key in ref_out:
         try:
             self.assertEqual(ref_out[key], this_out[key])
         except ValueError:
             np.testing.assert_array_equal(ref_out[key], this_out[key])
     for filename in os.listdir(
             os.path.join(module_dir, "..", "..", "test_files",
                          "real_run")):
         self.assertEqual(os.path.isfile(filename), True)
     os.chdir(module_dir)
Example #5
0
 def generate_multi_job_dict():
     """
     Used to generate test dictionary for multiple jobs
     """
     multi_job_dict = {}
     for file in multi_job_out_names:
         outputs = QCOutput.multiple_outputs_from_file(QCOutput, os.path.join(test_dir, file), keep_sub_files=False)
         data = []
         for sub_output in outputs:
             data.append(sub_output.data)
         multi_job_dict[file] = data
     dumpfn(multi_job_dict, "multi_job.json")
Example #6
0
 def process_qchemrun(dir_name, taskname, input_file, output_file):
     """
     Process a QChem calculation, aka an input/output pair.
     """
     qchem_input_file = os.path.join(dir_name, input_file)
     qchem_output_file = os.path.join(dir_name, output_file)
     d = QCOutput(qchem_output_file).data
     temp_input = QCInput.from_file(qchem_input_file)
     d["input"] = {}
     d["input"]["molecule"] = temp_input.molecule
     d["input"]["rem"] = temp_input.rem
     d["input"]["opt"] = temp_input.opt
     d["input"]["pcm"] = temp_input.pcm
     d["input"]["solvent"] = temp_input.solvent
     d["task"] = {"type": taskname, "name": taskname}
     return d
Example #7
0
class QChemSCFErrorHandler(ErrorHandler):
    """
    QChem ErrorHandler class that addresses SCF non-convergence.
    """

    is_monitor = False

    def __init__(self,
                 input_file="mol.qin",
                 output_file="mol.qout",
                 rca_gdm_thresh=1.0E-3,
                 scf_max_cycles=200):
        """
        Initializes the error handler from a set of input and output files.

        Args:
            input_file (str): Name of the QChem input file.
            output_file (str): Name of the QChem output file.
            rca_gdm_thresh (float): The threshold for the prior scf algorithm.
                If last deltaE is larger than the threshold try RCA_DIIS
                first, else, try DIIS_GDM first.
            scf_max_cycles (int): The max iterations to set to fix SCF failure.
        """
        self.input_file = input_file
        self.output_file = output_file
        self.scf_max_cycles = scf_max_cycles
        self.geom_max_cycles = geom_max_cycles
        self.qcinp = QCInput.from_file(self.input_file)
        self.outdata = None
        self.errors = None
        self.qchem_job = qchem_job

    def check(self):
        # Checks output file for errors.
        self.outdata = QCOutput(self.output_file).data
        self.errors = self.outdata.get("errors")
        return len(self.errors) > 0

    def correct(self):
        print("This hasn't been implemented yet!")
        return {"errors": self.errors, "actions": None}
Example #8
0
 def setUpClass(cls):
     out_file = os.path.join(module_dir, "..", "..", "test_files",
                             "FF_working", "test.qout.opt_1")
     qc_out = QCOutput(filename=out_file)
     cls.act_mol = qc_out.data["molecule_from_optimized_geometry"]
Example #9
0
# coding: utf-8

from __future__ import division, print_function, unicode_literals, absolute_import

import os

from atomate.qchem.workflows.base.double_FF_opt import get_wf_double_FF_opt
from fireworks.core.launchpad import LaunchPad
from pymatgen.io.qchem_io.outputs import QCOutput

out_file = os.path.join("/global/cscratch1/sd/sblau", "FF_working",
                        "test.qout.opt_0")
qc_out = QCOutput(filename=out_file)
act_mol = qc_out.data["initial_molecule"]
wf = get_wf_double_FF_opt(molecule=act_mol,
                          pcm_dielectric=10.0,
                          max_cores=32,
                          qchem_input_params={
                              "basis_set": "6-311++g**",
                              "overwrite_inputs": {
                                  "rem": {
                                      "sym_ignore": "true"
                                  }
                              }
                          })
lp = LaunchPad.auto_load()
lp.add_wf(wf)
Example #10
0
    def test_torsion_potential(self):
        # location of test files
        test_tor_files = os.path.join(module_dir, "..", "..", "test_files",
                                      "torsion_wf")
        # define starting molecule and torsion potential workflow object
        initial_qcin = QCInput.from_file(
            os.path.join(test_tor_files, "initial_opt", "mol.qin"))
        initial_mol = initial_qcin.molecule
        atom_indexes = [6, 8, 9, 10]
        angles = [0.0, 90.0, 180.0]
        rem = []
        # add the first rem section
        rem.append({
            "jobtype": "opt",
            "method": "wb97m-v",
            "basis": "def2-tzvppd",
            "gen_scfman": "true",
            "geom_opt_max_cycles": 75,
            "max_scf_cycles": 300,
            "scf_algorithm": "diis",
            "scf_guess": "sad",
            "sym_ignore": "true",
            "symmetry": "false",
            "thresh": 14
        })

        # the second rem section
        rem.append({
            "jobtype": "opt",
            "method": "wb97m-v",
            "basis": "def2-tzvppd",
            "geom_opt_max_cycles": 75,
            "max_scf_cycles": 300,
            "scf_algorithm": "diis",
            "scf_guess": "sad",
            "sym_ignore": "true",
            "symmetry": "false",
            "thresh": 14
        })

        real_wf = get_wf_torsion_potential(molecule=initial_mol,
                                           atom_indexes=atom_indexes,
                                           angles=angles,
                                           rem=rem,
                                           db_file=">>db_file<<")
        # use powerup to replace run with fake run
        # def ref_dirs
        ref_dirs = {
            "initial_opt": os.path.join(test_tor_files, "initial_opt"),
            "opt_0": os.path.join(test_tor_files, "opt_0"),
            "opt_90": os.path.join(test_tor_files, "opt_90"),
            "opt_180": os.path.join(test_tor_files, "opt_180")
        }
        fake_wf = use_fake_qchem(real_wf, ref_dirs)

        self.lp.add_wf(fake_wf)
        rapidfire(
            self.lp,
            fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")}))

        wf_test = self.lp.get_wf_by_fw_id(1)
        self.assertTrue(
            all([s == "COMPLETED" for s in wf_test.fw_states.values()]))

        # Checking of the inputs happens in fake_run_qchem so there is no point to retest the inputs
        # Check the output info that gets inserted in the DB
        init_opt = self.get_task_collection().find_one(
            {"task_label": "initial_opt"})
        init_opt_final_mol = Molecule.from_dict(
            init_opt["output"]["optimized_molecule"])
        init_opt_final_e = init_opt["output"]["final_energy"]
        # parse output file
        act_init_opt_out = QCOutput(
            os.path.join(test_tor_files, "initial_opt", "mol.qout"))
        act_init_opt_mol = act_init_opt_out.data[
            "molecule_from_optimized_geometry"]
        act_init_opt_final_e = act_init_opt_out.data["final_energy"]

        np.testing.assert_equal(act_init_opt_mol.species,
                                init_opt_final_mol.species)
        np.testing.assert_allclose(act_init_opt_mol.cart_coords,
                                   init_opt_final_mol.cart_coords,
                                   atol=0.0001)
        np.testing.assert_equal(act_init_opt_final_e, init_opt_final_e)

        # Optimization of 0 torsion
        opt_0 = self.get_task_collection().find_one({"task_label": "opt_0"})
        opt_0_final_mol = Molecule.from_dict(
            opt_0["output"]["optimized_molecule"])
        opt_0_final_e = opt_0["output"]["final_energy"]
        # parse output file
        act_opt_0_out = QCOutput(
            os.path.join(test_tor_files, "opt_0", "mol.qout"))
        act_opt_0_mol = act_opt_0_out.data["molecule_from_optimized_geometry"]
        act_opt_0_final_e = act_opt_0_out.data["final_energy"]

        np.testing.assert_equal(act_opt_0_mol.species, opt_0_final_mol.species)
        np.testing.assert_allclose(act_opt_0_mol.cart_coords,
                                   opt_0_final_mol.cart_coords,
                                   atol=0.0001)
        np.testing.assert_equal(act_opt_0_final_e, opt_0_final_e)

        # Optimization of 90 torsion
        opt_90 = self.get_task_collection().find_one({"task_label": "opt_90"})
        opt_90_final_mol = Molecule.from_dict(
            opt_90["output"]["optimized_molecule"])
        opt_90_final_e = opt_90["output"]["final_energy"]
        # parse output file
        act_opt_90_out = QCOutput(
            os.path.join(test_tor_files, "opt_90", "mol.qout"))
        act_opt_90_mol = act_opt_90_out.data[
            "molecule_from_optimized_geometry"]
        act_opt_90_final_e = act_opt_90_out.data["final_energy"]

        np.testing.assert_equal(act_opt_90_mol.species,
                                opt_90_final_mol.species)
        np.testing.assert_allclose(act_opt_90_mol.cart_coords,
                                   opt_90_final_mol.cart_coords,
                                   atol=0.0001)
        np.testing.assert_equal(act_opt_90_final_e, opt_90_final_e)

        # Optimization of 180 torsion
        opt_180 = self.get_task_collection().find_one(
            {"task_label": "opt_180"})
        opt_180_final_mol = Molecule.from_dict(
            opt_180["output"]["optimized_molecule"])
        opt_180_final_e = opt_180["output"]["final_energy"]
        # parse output file
        act_opt_180_out = QCOutput(
            os.path.join(test_tor_files, "opt_180", "mol.qout"))
        act_opt_180_mol = act_opt_180_out.data[
            "molecule_from_optimized_geometry"]
        act_opt_180_final_e = act_opt_180_out.data["final_energy"]

        np.testing.assert_equal(act_opt_180_mol.species,
                                opt_180_final_mol.species)
        np.testing.assert_allclose(act_opt_180_mol.cart_coords,
                                   opt_180_final_mol.cart_coords,
                                   atol=0.0001)
        np.testing.assert_equal(act_opt_180_final_e, opt_180_final_e)
Example #11
0
 def check(self):
     # Checks output file for errors.
     self.outdata = QCOutput(self.output_file).data
     self.errors = self.outdata.get("errors")
     return len(self.errors) > 0
Example #12
0
class QChemErrorHandler(ErrorHandler):
    """
    Master QChemErrorHandler class that handles a number of common errors
    that occur during QChem runs.
    """

    is_monitor = False

    def __init__(self,
                 input_file="mol.qin",
                 output_file="mol.qout",
                 scf_max_cycles=200,
                 geom_max_cycles=200):
        """
        Initializes the error handler from a set of input and output files.

        Args:
            input_file (str): Name of the QChem input file.
            output_file (str): Name of the QChem output file.
            scf_max_cycles (int): The max iterations to set to fix SCF failure.
            geom_max_cycles (int): The max iterations to set to fix geometry
                optimization failure.
        """
        self.input_file = input_file
        self.output_file = output_file
        self.scf_max_cycles = scf_max_cycles
        self.geom_max_cycles = geom_max_cycles
        self.qcinp = QCInput.from_file(self.input_file)
        self.outdata = None
        self.errors = []

    def check(self):
        # Checks output file for errors.
        self.outdata = QCOutput(self.output_file).data
        self.errors = self.outdata.get("errors")
        return len(self.errors) > 0

    def correct(self):
        backup({self.input_file, self.output_file})
        actions = []

        if "SCF_failed_to_converge" in self.errors:
            # Check number of SCF cycles. If not set or less than scf_max_cycles,
            # increase to that value and rerun. If already set, check if
            # scf_algorithm is unset or set to DIIS, in which case set to RCA-DIIS.
            # Otherwise, tell user to call SCF error handler and do nothing.
            if self.qcinp.rem.get("max_scf_cycles") != str(
                    self.scf_max_cycles):
                self.qcinp.rem["max_scf_cycles"] = self.scf_max_cycles
                actions.append({"max_scf_cycles": self.scf_max_cycles})
            elif self.qcinp.rem.get("scf_algorithm", "diis").lower() == "diis":
                self.qcinp.rem["scf_algorithm"] = "rca_diis"
                actions.append({"scf_algorithm": "rca_diis"})
                if self.qcinp.rem.get("gen_scfman"):
                    self.qcinp.rem["gen_scfman"] = False
                    actions.append({"gen_scfman": False})
            else:
                print(
                    "More advanced changes may impact the SCF result. Use the SCF error handler"
                )

        elif "out_of_opt_cycles" in self.errors:
            # Check number of opt cycles. If less than geom_max_cycles, increase
            # to that value, set last geom as new starting geom and rerun.
            if self.qcinp.rem.get(
                    "geom_opt_max_cycles") != self.geom_max_cycles:
                self.qcinp.rem["geom_opt_max_cycles"] = self.geom_max_cycles
                actions.append({"geom_max_cycles:": self.scf_max_cycles})
                if len(self.outdata.get("energy_trajectory")) > 1:
                    if self.qcinp.molecule.spin_multiplicity != self.outdata.get(
                            "molecule_from_last_geometry").spin_multiplicity:
                        raise AssertionError('Multiplicities should match!')
                    if self.qcinp.molecule.charge != self.outdata.get(
                            "molecule_from_last_geometry").charge:
                        raise AssertionError('Charges should match!')
                    self.qcinp.molecule = self.outdata.get(
                        "molecule_from_last_geometry")
                    actions.append({"molecule": "molecule_from_last_geometry"})
            else:
                print(
                    "How do I get the geometry optimization converged when already at the maximum number of cycles?"
                )

        elif "unable_to_determine_lamda" in self.errors:
            # Set last geom as new starting geom and rerun. If no opt cycles,
            # use diff SCF strat? Diff initial guess? Change basis?
            if len(self.outdata.get("energy_trajectory")) > 1:
                if self.qcinp.molecule.spin_multiplicity != self.outdata.get(
                        "molecule_from_last_geometry").spin_multiplicity:
                    raise AssertionError('Multiplicities should match!')
                if self.qcinp.molecule.charge != self.outdata.get(
                        "molecule_from_last_geometry").charge:
                    raise AssertionError('Charges should match!')
                self.qcinp.molecule = self.outdata.get(
                    "molecule_from_last_geometry")
                actions.append({"molecule": "molecule_from_last_geometry"})
            elif self.qcinp.rem.get("scf_algorithm", "diis").lower() == "diis":
                self.qcinp.rem["scf_algorithm"] = "rca_diis"
                actions.append({"scf_algorithm": "rca_diis"})
                if self.qcinp.rem.get("gen_scfman"):
                    self.qcinp.rem["gen_scfman"] = False
                    actions.append({"gen_scfman": False})
            else:
                print(
                    "Use a different initial guess? Perhaps a different basis?"
                )

        elif "linear_dependent_basis" in self.errors:
            # DIIS -> RCA_DIIS. If already RCA_DIIS, change basis?
            if self.qcinp.rem.get("scf_algorithm", "diis").lower() == "diis":
                self.qcinp.rem["scf_algorithm"] = "rca_diis"
                actions.append({"scf_algorithm": "rca_diis"})
                if self.qcinp.rem.get("gen_scfman"):
                    self.qcinp.rem["gen_scfman"] = False
                    actions.append({"gen_scfman": False})
            else:
                print("Perhaps use a better basis?")

        elif "failed_to_transform_coords" in self.errors:
            # Check for symmetry flag in rem. If not False, set to False and rerun.
            # If already False, increase threshold?
            if not self.qcinp.rem.get("sym_ignore") or self.qcinp.rem.get(
                    "symmetry"):
                self.qcinp.rem["sym_ignore"] = True
                self.qcinp.rem["symmetry"] = False
                actions.append({"sym_ignore": True})
                actions.append({"symmetry": False})
            else:
                print("Perhaps increase the threshold?")

        elif "input_file_error" in self.errors:
            print(
                "Something is wrong with the input file. Examine error message by hand."
            )
            return {"errors": self.errors, "actions": None}

        elif "failed_to_read_input" in self.errors:
            # Almost certainly just a temporary problem that will not be encountered again. Rerun job as-is.
            actions.append({"rerun job as-is"})

        elif "IO_error" in self.errors:
            # Almost certainly just a temporary problem that will not be encountered again. Rerun job as-is.
            actions.append({"rerun job as-is"})

        elif "unknown_error" in self.errors:
            print("Examine error message by hand.")
            return {"errors": self.errors, "actions": None}

        else:
            # You should never get here. If correct is being called then errors should have at least one entry,
            # in which case it should have been caught by the if/elifs above.
            print(
                "If you get this message, something has gone terribly wrong!")
            return {"errors": self.errors, "actions": None}

        os.rename(self.input_file, self.input_file + ".last")
        self.qcinp.write_file(self.input_file)
        return {"errors": self.errors, "actions": actions}
Example #13
0
 def setUp(self, lpad=False):
     out_file = os.path.join(module_dir, "..", "..", "test_files",
                             "FF_working", "test.qout.opt_0")
     qc_out = QCOutput(filename=out_file)
     self.act_mol = qc_out.data["initial_molecule"]
     super(TestCore, self).setUp(lpad=False)