def is_complete(self, output_file: Path) -> bool: """ Determines if the given output file completed successfully. :param output_file: a Path object pointing to the output file :return: True if successful, False otherwise :raises AttributeError: if this method doesn't support the current step program """ output_filepath = Path(output_file).resolve() if self.step_program == "gaussian16": num_matches = len( find_string(output_filepath, "Normal termination")) opt_freq = sum([ self.current_step_config["opt"], self.current_step_config["freq"] ]) if opt_freq > 0: return num_matches == opt_freq elif self.current_step_config["single_point"]: return num_matches == 1 elif self.step_program == "gamess": num_matches = len( find_string(output_filepath, "GAMESS TERMINATED NORMALLY")) return num_matches == sum([self.current_step_config["opt"]]) else: raise AttributeError("Unknown program: {}".format( self.step_program))
def needs_restart(self): normal_t_count = len(find_string(self.output_file, "Normal termination")) if "opt" in self.route and "freq" in self.route: return normal_t_count < 2 elif "opt" in self.route or "freq" in self.route or "# Restart" in self.route: return normal_t_count < 1 return False
def get_route(input_file: Path) -> str: """ :return: """ matches = find_string(input_file, "#") if len(matches) == 0: raise AttributeError("Unable to find route in input file: {}".format(input_file)) else: return matches[0].strip()
def get_energy(output_file: str, format: str, excited_state: bool = False) -> float: """ Returns the energy from the given output file in units of electronvolts (eV). :param output_file: the path to the output file :param format: the format of the output file :param excited_state: whether to extract excited state energy :return: an energy in eV """ if format == "gaussian16": energy_line = find_string(Path(output_file).resolve(), "SCF Done")[-1] energy = float(energy_line.split("A.U.")[0].split()[-1]) * 27.2113246 elif format == "gamess": raise NotImplementedError("GAMESS get_energy not implemented") else: raise AttributeError("Unable to obtain energy from file format '{}'".format(format)) return energy
def get_new_route(self): if not self.output_file.exists(): return None if self.needs_restart() and not self.error_fail(): self.clear_gau_files() normal_t_count = len(find_string(self.output_file, "Normal termination")) if "opt" in self.route and "freq" in self.route: if normal_t_count == 1: return self.restart_freq() elif normal_t_count == 0: return self.restart_opt() elif "opt" in self.route: return self.restart_opt() elif "freq" in self.route: return self.restart_freq() elif self.convergence_fail() or self.formbx_fail() or self.link_9999_fail(): self.clear_gau_files() return self.restart_opt(additional_opt_options=["recalcfc=4"])
def formbx_fail(self): return len(find_string(self.output_file, "FormBX had a problem.")) > 0
def convergence_fail(self): return len(find_string(self.output_file, "Convergence failure -- run terminated.")) > 0
def link_9999_fail(self): return len(find_string(self.output_file, "Error termination request processed by link 9999.")) > 0
def error_fail(self): return len(find_string(self.output_file, "Error termination")) > 0
def get_scf_energies(self): scf_energies = find_string(self.output_file, "SCF Done:") energies = [float(line.split("=")[1].split('A.U.')[0].strip()) for line in scf_energies] return energies