예제 #1
0
파일: jobs.py 프로젝트: czhengsci/custodian
 def _run_qchem_on_alcf(self, log_file_object=None):
     parent_qcinp = QcInput.from_file(self.input_file)
     njobs = len(parent_qcinp.jobs)
     return_codes = []
     alcf_cmds = []
     qc_jobids = []
     for i, j in enumerate(parent_qcinp.jobs):
         qsub_cmd = copy.deepcopy(self.current_command)
         sub_input_filename = "alcf_{}_{}".format(i+1, self.input_file)
         sub_output_filename = "alcf_{}_{}".format(i+1, self.output_file)
         sub_log_filename = "alcf_{}_{}".format(i+1, self.qclog_file)
         qsub_cmd[-2] = sub_input_filename
         sub_qcinp = QcInput([copy.deepcopy(j)])
         if "scf_guess" in sub_qcinp.jobs[0].params["rem"] and \
                 sub_qcinp.jobs[0].params["rem"]["scf_guess"] == "read":
             sub_qcinp.jobs[0].params["rem"].pop("scf_guess")
         if i > 0:
             if isinstance(j.mol, str) and j.mol == "read":
                 prev_qcout_filename = "alcf_{}_{}".format(i+1-1, self.output_file)
                 prev_qcout = QcOutput(prev_qcout_filename)
                 prev_final_mol = prev_qcout.data[0]["molecules"][-1]
                 j.mol = prev_final_mol
         sub_qcinp.write_file(sub_input_filename)
         logging.info("The command to run QChem is {}".format(' '.join(qsub_cmd)))
         alcf_cmds.append(qsub_cmd)
         p = subprocess.Popen(qsub_cmd,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
         out, err = p.communicate()
         qc_jobid = int(out.strip())
         qc_jobids.append(qc_jobid)
         cqwait_cmd = shlex.split("cqwait {}".format(qc_jobid))
         subprocess.call(cqwait_cmd)
         output_file_name = "{}.output".format(qc_jobid)
         cobaltlog_file_name = "{}.cobaltlog".format(qc_jobid)
         with open(cobaltlog_file_name) as f:
             cobaltlog_last_line = f.readlines()[-1]
             exit_code_pattern = re.compile("an exit code of (?P<code>\d+);")
             m = exit_code_pattern.search(cobaltlog_last_line)
             if m:
                 rc = float(m.group("code"))
             else:
                 rc = -99999
             return_codes.append(rc)
         for name_change_trial in range(10):
             if not os.path.exists(output_file_name):
                 message = "{} is not found in {}, {}th wait " \
                           "for 5 mins\n".format(
                                 output_file_name,
                                 os.getcwd(), name_change_trial)
                 logging.info(message)
                 if log_file_object:
                     log_file_object.writelines([message])
                 time.sleep(60 * 5)
                 pass
             else:
                 message = "Found qchem output file {} in {}, change file " \
                           "name\n".format(output_file_name,
                                           os.getcwd(),
                                           name_change_trial)
                 logging.info(message)
                 if log_file_object:
                     log_file_object.writelines([message])
                 break
         log_file_object.flush()
         os.fsync(log_file_object.fileno())
         shutil.move(output_file_name, sub_output_filename)
         shutil.move(cobaltlog_file_name, sub_log_filename)
     overall_return_code = min(return_codes)
     with open(self.output_file, "w") as out_file_object:
         for i, job_cmd, rc, qc_jobid in zip(range(njobs), alcf_cmds, return_codes, qc_jobids):
             sub_output_filename = "alcf_{}_{}".format(i+1, self.output_file)
             sub_log_filename = "alcf_{}_{}".format(i+1, self.qclog_file)
             with open(sub_output_filename) as sub_out_file_object:
                 header_lines = ["Running Job {} of {} {}\n".format(i + 1, njobs, self.input_file),
                                 " ".join(job_cmd) + "\n"]
                 if i > 0:
                     header_lines = ['', ''] + header_lines
                 sub_out = sub_out_file_object.readlines()
                 out_file_object.writelines(header_lines)
                 out_file_object.writelines(sub_out)
                 if rc < 0 and rc != -99999:
                     out_file_object.writelines(["Application {} exit codes: {}\n".format(qc_jobid, rc), '\n', '\n'])
             if log_file_object:
                 with open(sub_log_filename) as sub_log_file_object:
                     sub_log = sub_log_file_object.readlines()
                     log_file_object.writelines(sub_log)
     return overall_return_code
예제 #2
0
def main():
    import argparse
    parser = argparse.ArgumentParser(
        description="Run A QChem Job for a QChem Input File")
    parser.add_argument("-i",
                        "--input",
                        dest="input",
                        type=str,
                        required=True,
                        help="the QChem output file with imaginary frequency")
    parser.add_argument("-o",
                        "--output",
                        dest="output",
                        type=str,
                        required=True,
                        help="the QChem input file with perturbed geometry")
    parser.add_argument("-s",
                        "--scale",
                        dest="scale",
                        type=float,
                        default=0.3,
                        help="the scale factor to perturb molecule")
    parser.add_argument("-r",
                        "--reverse",
                        dest="reverse",
                        action="store_true",
                        help="use reversed direction to perturb molecule")
    parser.add_argument("-v",
                        "--verbose",
                        dest="verbose",
                        action="store_true",
                        help="print parameters")
    options = parser.parse_args()
    qcout = QcOutput(options.input)
    charge = None
    spin_multiplicity = None
    for d in qcout.data:
        j = d["input"]
        if j.charge is not None:
            charge = j.charge
        if j.spin_multiplicity is not None:
            spin_multiplicity = j.spin_multiplicity
    if qcout.data[-1]['frequencies'][0]["frequency"] < -0.00:
        old_mol = qcout.data[-1]["molecules"][-1]
        vib_mode = qcout.data[-1]['frequencies'][0]["vib_mode"]
        if options.verbose:
            if options.reverse:
                direction_text = "User forward direction"
            else:
                direction_text = "User reversed direction"
            print("{} with scale factor {}".format(direction_text,
                                                   options.scale))
        new_mol = perturb_molecule(old_mol,
                                   vib_mode,
                                   reversed_direction=options.reverse,
                                   perturb_scale=options.scale)
        qctask_freq = qcout.data[-1]["input"]
        qctask_freq.mol = "read"
        qctask_freq.charge = charge
        qctask_freq.spin_multiplicity = spin_multiplicity
        qctask_opt = copy.deepcopy(qctask_freq)
        qctask_opt.params["rem"]["jobtype"] = "opt"
        qctask_opt.params["rem"].pop("scf_guess", None)
        qctask_opt.mol = new_mol
        qcinp = QcInput([qctask_opt, qctask_freq])
        qcinp.write_file(options.output)
    else:
        raise ValueError(
            "Must have an imaginary frequency to perturb the molecule")
예제 #3
0
 def _run_qchem_on_alcf(self, log_file_object=None):
     parent_qcinp = QcInput.from_file(self.input_file)
     njobs = len(parent_qcinp.jobs)
     return_codes = []
     alcf_cmds = []
     qc_jobids = []
     for i, j in enumerate(parent_qcinp.jobs):
         qsub_cmd = copy.deepcopy(self.current_command)
         sub_input_filename = "alcf_{}_{}".format(i + 1, self.input_file)
         sub_output_filename = "alcf_{}_{}".format(i + 1, self.output_file)
         sub_log_filename = "alcf_{}_{}".format(i + 1, self.qclog_file)
         qsub_cmd[-2] = sub_input_filename
         sub_qcinp = QcInput([copy.deepcopy(j)])
         if "scf_guess" in sub_qcinp.jobs[0].params["rem"] and \
                 sub_qcinp.jobs[0].params["rem"]["scf_guess"] == "read":
             sub_qcinp.jobs[0].params["rem"].pop("scf_guess")
         if i > 0:
             if isinstance(j.mol, str) and j.mol == "read":
                 prev_qcout_filename = "alcf_{}_{}".format(
                     i + 1 - 1, self.output_file)
                 prev_qcout = QcOutput(prev_qcout_filename)
                 prev_final_mol = prev_qcout.data[0]["molecules"][-1]
                 j.mol = prev_final_mol
         sub_qcinp.write_file(sub_input_filename)
         logging.info("The command to run QChem is {}".format(
             ' '.join(qsub_cmd)))
         alcf_cmds.append(qsub_cmd)
         p = subprocess.Popen(qsub_cmd,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
         out, err = p.communicate()
         qc_jobid = int(out.strip())
         qc_jobids.append(qc_jobid)
         cqwait_cmd = shlex.split("cqwait {}".format(qc_jobid))
         subprocess.call(cqwait_cmd)
         output_file_name = "{}.output".format(qc_jobid)
         cobaltlog_file_name = "{}.cobaltlog".format(qc_jobid)
         with open(cobaltlog_file_name) as f:
             cobaltlog_last_line = f.readlines()[-1]
             exit_code_pattern = re.compile(
                 "an exit code of (?P<code>\d+);")
             m = exit_code_pattern.search(cobaltlog_last_line)
             if m:
                 rc = float(m.group("code"))
             else:
                 rc = -99999
             return_codes.append(rc)
         for name_change_trial in range(10):
             if not os.path.exists(output_file_name):
                 message = "{} is not found in {}, {}th wait " \
                           "for 5 mins\n".format(
                                 output_file_name,
                                 os.getcwd(), name_change_trial)
                 logging.info(message)
                 if log_file_object:
                     log_file_object.writelines([message])
                 time.sleep(60 * 5)
                 pass
             else:
                 message = "Found qchem output file {} in {}, change file " \
                           "name\n".format(output_file_name,
                                           os.getcwd(),
                                           name_change_trial)
                 logging.info(message)
                 if log_file_object:
                     log_file_object.writelines([message])
                 break
         log_file_object.flush()
         os.fsync(log_file_object.fileno())
         shutil.move(output_file_name, sub_output_filename)
         shutil.move(cobaltlog_file_name, sub_log_filename)
     overall_return_code = min(return_codes)
     with open(self.output_file, "w") as out_file_object:
         for i, job_cmd, rc, qc_jobid in zip(range(njobs), alcf_cmds,
                                             return_codes, qc_jobids):
             sub_output_filename = "alcf_{}_{}".format(
                 i + 1, self.output_file)
             sub_log_filename = "alcf_{}_{}".format(i + 1, self.qclog_file)
             with open(sub_output_filename) as sub_out_file_object:
                 header_lines = [
                     "Running Job {} of {} {}\n".format(
                         i + 1, njobs, self.input_file),
                     " ".join(job_cmd) + "\n"
                 ]
                 if i > 0:
                     header_lines = ['', ''] + header_lines
                 sub_out = sub_out_file_object.readlines()
                 out_file_object.writelines(header_lines)
                 out_file_object.writelines(sub_out)
                 if rc < 0 and rc != -99999:
                     out_file_object.writelines([
                         "Application {} exit codes: {}\n".format(
                             qc_jobid, rc), '\n', '\n'
                     ])
             if log_file_object:
                 with open(sub_log_filename) as sub_log_file_object:
                     sub_log = sub_log_file_object.readlines()
                     log_file_object.writelines(sub_log)
     return overall_return_code
예제 #4
0
def main():
    import argparse
    parser = argparse.ArgumentParser(
        description="Run A QChem Job for a QChem Input File")
    parser.add_argument("-f",
                        "--filename",
                        dest="filename",
                        type=str,
                        required=True,
                        help="the QChem input filename")
    parser.add_argument("-e",
                        "--eliminate",
                        dest="eli_img",
                        action="store_true",
                        help="whether to eliminate imaginary frequency")
    parser.add_argument("-b",
                        "--mixed_basis",
                        dest="mixed_basis",
                        type=json.loads,
                        required=False,
                        help="The mixed basis as a dict")
    parser.add_argument("-a",
                        "--mixed_aux_basis",
                        dest="mixed_aux_basis",
                        type=json.loads,
                        required=False,
                        help="The mixed auxiliary basis as a dict")
    parser.add_argument("-s",
                        "--solvent",
                        dest="solvent",
                        type=str,
                        required=False,
                        help="the implicit solvent")
    parser.add_argument("-n",
                        "--run_name",
                        dest="run_name",
                        type=str,
                        default=None,
                        help="the implicit solvent")
    options = parser.parse_args()
    call_qchem_task(options.filename,
                    options.solvent,
                    options.mixed_basis,
                    options.mixed_aux_basis,
                    run_name=options.run_name)
    if options.eli_img:
        base_filename = os.path.splitext(options.filename)[0]
        output_filename = base_filename + ".qcout"
        qcout = QcOutput(output_filename)
        charge = None
        spin_multiplicity = None
        for d in qcout.data:
            j = d["input"]
            if j.charge is not None:
                charge = j.charge
            if j.spin_multiplicity is not None:
                spin_multiplicity = j.spin_multiplicity
        if qcout.data[-1]['frequencies'][0]["frequency"] < -0.00:
            os.system("tar czvf img_freq_1.tar.gz *")
            old_mol = qcout.data[-1]["molecules"][-1]
            vib_mode = qcout.data[-1]['frequencies'][0]["vib_mode"]
            new_mol = perturb_molecule(old_mol, vib_mode)
            qctask_freq = qcout.data[-1]["input"]
            qctask_freq.mol = "read"
            qctask_freq.charge = charge
            qctask_freq.spin_multiplicity = spin_multiplicity
            qctask_opt = copy.deepcopy(qctask_freq)
            qctask_opt.params["rem"]["jobtype"] = "opt"
            qctask_opt.params["rem"].pop("scf_guess", None)
            qctask_opt.mol = new_mol
            qcinp = QcInput([qctask_opt, qctask_freq])
            eli_file_1 = base_filename + "_eli_img_1.qcinp"
            qcinp.write_file(eli_file_1)
            call_qchem_task(eli_file_1,
                            options.solvent,
                            options.mixed_basis,
                            options.mixed_aux_basis,
                            run_name=options.run_name)

            output_filename = base_filename + "_eli_img_1.qcout"
            qcout = QcOutput(output_filename)
            if qcout.data[-1]['frequencies'][0]["frequency"] < -0.00:
                os.system("tar czvf img_freq_2.tar.gz *")
                old_mol = qcout.data[-1]["molecules"][-1]
                vib_mode = qcout.data[-1]['frequencies'][0]["vib_mode"]
                new_mol = perturb_molecule(old_mol, vib_mode)
                qctask_freq = qcout.data[-1]["input"]
                qctask_freq.mol = "read"
                qctask_freq.charge = charge
                qctask_freq.spin_multiplicity = spin_multiplicity
                qctask_opt = copy.deepcopy(qctask_freq)
                qctask_opt.params["rem"]["jobtype"] = "opt"
                qctask_opt.params["rem"].pop("scf_guess", None)
                qctask_opt.mol = new_mol
                qcinp = QcInput([qctask_opt, qctask_freq])
                for j in qcinp.jobs:
                    j.set_dft_grid(128, 302)
                    j.set_integral_threshold(12)
                    if j.params["rem"]["jobtype"] == "opt":
                        j.scale_geom_opt_threshold(0.1, 0.1, 0.1)
                        j.set_geom_max_iterations(100)
                eli_file_2 = base_filename + "_eli_img_2.qcinp"
                qcinp.write_file(eli_file_2)
                call_qchem_task(eli_file_2,
                                options.solvent,
                                options.mixed_basis,
                                options.mixed_aux_basis,
                                run_name=options.run_name)

                output_filename = base_filename + "_eli_img_2.qcout"
                qcout = QcOutput(output_filename)
                if qcout.data[-1]['frequencies'][0]["frequency"] < -0.00:
                    os.system("tar czvf img_freq_3.tar.gz *")
                    old_mol = qcout.data[-1]["molecules"][-1]
                    vib_mode = qcout.data[-1]['frequencies'][0]["vib_mode"]
                    new_mol = perturb_molecule(old_mol, vib_mode)
                    qctask_freq = qcout.data[-1]["input"]
                    qctask_freq.mol = "read"
                    qctask_freq.charge = charge
                    qctask_freq.spin_multiplicity = spin_multiplicity
                    qctask_opt = copy.deepcopy(qctask_freq)
                    qctask_opt.params["rem"]["jobtype"] = "opt"
                    qctask_opt.params["rem"].pop("scf_guess", None)
                    qctask_opt.mol = new_mol
                    qcinp = QcInput([qctask_opt, qctask_freq])
                    for j in qcinp.jobs:
                        j.set_dft_grid(90, 590)
                        j.set_integral_threshold(12)
                        if j.params["rem"]["jobtype"] == "opt":
                            j.scale_geom_opt_threshold(0.1, 0.1, 0.1)
                            j.set_geom_max_iterations(100)
                    eli_file_3 = base_filename + "_eli_img_3.qcinp"
                    qcinp.write_file(eli_file_3)
                    call_qchem_task(eli_file_3,
                                    options.solvent,
                                    options.mixed_basis,
                                    options.mixed_aux_basis,
                                    run_name=options.run_name)