def test_parse_zpe(self): """Test the parse_zpe() function for parsing zero point energies""" path1 = os.path.join(ARC_PATH, 'arc', 'testing', 'freq', 'C2H6_freq_QChem.out') path2 = os.path.join(ARC_PATH, 'arc', 'testing', 'freq', 'CH2O_freq_molpro.out') path3 = os.path.join(ARC_PATH, 'arc', 'testing', 'freq', 'NO3_freq_QChem_fails_on_cclib.out') path4 = os.path.join(ARC_PATH, 'arc', 'testing', 'composite', 'SO2OO_CBS-QB3.log') zpe1, zpe2, zpe3, zpe4 = parser.parse_zpe(path1), parser.parse_zpe(path2), parser.parse_zpe(path3), \ parser.parse_zpe(path4) self.assertAlmostEqual(zpe1, 198.08311200000, 5) self.assertAlmostEqual(zpe2, 69.793662734869, 5) self.assertAlmostEqual(zpe3, 25.401064000000, 5) self.assertAlmostEqual(zpe4, 39.368057626223, 5)
def determine_scaling_factors( levels: List[Union[Level, dict, str]], ess_settings: Optional[dict] = None, init_log: Optional[bool] = True, ) -> list: """ Determine the zero-point energy, harmonic frequencies, and fundamental frequencies scaling factors for a given frequencies level of theory. Args: levels (list): A list of frequencies levels of theory for which scaling factors are determined. Entries are either Level instances, dictionaries, or simple string representations. If a single entry is given, it will be converted to a list. ess_settings (dict, optional): A dictionary of available ESS (keys) and a corresponding server list (values). init_log (bool, optional): Whether to initialize the logger. ``True`` to initialize. Should be ``True`` when called as a standalone, but ``False`` when called within ARC. Returns: list: The determined frequency scaling factors. """ if init_log: initialize_log(log_file='scaling_factor.log', project='Scaling Factors') if not isinstance(levels, (list, tuple)): levels = [levels] levels = [ Level(repr=level) if not isinstance(level, Level) else level for level in levels ] t0 = time.time() logger.info('\n\n\n') logger.info(HEADER) logger.info('\n\nstarting ARC...\n') # only run opt (fine) and freq job_types = initialize_job_types( dict()) # get the defaults, so no job type is missing job_types = {job_type: False for job_type in job_types.keys()} job_types['opt'], job_types['fine'], job_types['freq'] = True, True, True lambda_zpes, zpe_dicts, times = list(), list(), list() for level in levels: t1 = time.time() logger.info( f'\nComputing scaling factors at the {level} level of theory...\n\n' ) renamed_level = rename_level(str(level)) project = 'scaling_' + renamed_level project_directory = os.path.join(arc_path, 'Projects', 'scaling_factors', project) if os.path.isdir(project_directory): shutil.rmtree(project_directory) species_list = get_species_list() if level.method_type == 'composite': freq_level = None composite_method = level job_types['freq'] = False else: freq_level = level composite_method = None ess_settings = check_ess_settings(ess_settings or global_ess_settings) Scheduler(project=project, project_directory=project_directory, species_list=species_list, composite_method=composite_method, opt_level=freq_level, freq_level=freq_level, ess_settings=ess_settings, job_types=job_types, allow_nonisomorphic_2d=True) zpe_dict = dict() for spc in species_list: zpe_dict[spc.label] = parse_zpe( os.path.join(project_directory, 'output', 'Species', spc.label, 'geometry', 'freq.out')) * 1000 # convert to J/mol zpe_dicts.append(zpe_dict) lambda_zpes.append( calculate_truhlar_scaling_factors(zpe_dict=zpe_dict, level=str(level))) times.append(time_lapse(t1)) summarize_results(lambda_zpes=lambda_zpes, levels=[str(level) for level in levels], zpe_dicts=zpe_dicts, times=times, overall_time=time_lapse(t0)) logger.info('\n\n\n') logger.info(HEADER) harmonic_freq_scaling_factors = [ lambda_zpe * 1.014 for lambda_zpe in lambda_zpes ] return harmonic_freq_scaling_factors