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
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")
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
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)