From 941bc1e9c79e35f3191eef3348bac11b23b15056 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Thu, 27 Jun 2024 22:51:25 +0300 Subject: [PATCH 01/12] Minor: Style modifications to common --- arc/common.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arc/common.py b/arc/common.py index c43d6d9f0a..72aa79e16d 100644 --- a/arc/common.py +++ b/arc/common.py @@ -1703,9 +1703,10 @@ def is_xyz_mol_match(mol: 'Molecule', for element, count in element_dict_mol.items(): if element not in element_dict_xyz or element_dict_xyz[element] != count: - return False + return False return True + def convert_to_hours(time_str:str) -> float: """Convert walltime string in format HH:MM:SS to hours. From 80876f17541fe6ab286cd1d72aa928de881cd2f9 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Thu, 4 Jul 2024 22:30:45 +0300 Subject: [PATCH 02/12] Added freq_scale_factors to data --- data/freq_scale_factors.yml | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 data/freq_scale_factors.yml diff --git a/data/freq_scale_factors.yml b/data/freq_scale_factors.yml new file mode 100644 index 0000000000..9d26adeb7b --- /dev/null +++ b/data/freq_scale_factors.yml @@ -0,0 +1,67 @@ +freq_scale_factors: + # Refer to https://comp.chem.umn.edu/freqscale/index.html for future updates of these factors + # Sources: + # [1] I.M. Alecu, J. Zheng, Y. Zhao, D.G. Truhlar, J. Chem. Theory Comput. 2010, 6, 2872, DOI: 10.1021/ct100326h + # [2] http://cccbdb.nist.gov/vibscalejust.asp + # [3] http://comp.chem.umn.edu/freqscale/190107_Database_of_Freq_Scale_Factors_v4.pdf + # [4] Calculated as described in 10.1021/ct100326h + # [5] J.A. Montgomery, M.J. Frisch, J. Chem. Phys. 1999, 110, 2822–2827, DOI: 10.1063/1.477924 + 'hf/sto3g, software: gaussian': 0.817 # [2] + 'hf/6-31g, software: gaussian': 0.903 # [2] + 'hf/6-31g(d), software: gaussian': 0.899 # [2] + 'hf/6-31g(d,p), software: gaussian': 0.903 # [2] + 'hf/6-31+g(d,p), software: gaussian': 0.928 # 0.915 * 1.014, [1] Table 7 + 'pm3, software: gaussian': 0.953 # 0.940 * 1.014, [1] Table 7, the 0.940 value is the ZPE scale factor + 'pm6, software: gaussian': 1.093 # 1.078 * 1.014, [1] Table 7, the 1.078 value is the ZPE scale factor + 'b3lyp/6-31g(d,p), software: gaussian': 0.961 # [2] + 'b3lyp/6-311g(d,p), software: gaussian': 0.967 # [2] + 'b3lyp/6-311+g(3df,2p), software: gaussian': 0.967 # [2] + 'b3lyp/6-311+g(3df,2pd), software: gaussian': 0.970 # [2] + 'b3lyp/cc-pvtz, software: gaussian': 0.998 # [2] + 'b3lyp/aug-cc-pvtz, software: gaussian': 0.999 # [2] + 'b3lyp/def2tzvp, software: gaussian': 0.999 # [2] + 'm062x/6-31g(d,p), software: gaussian': 0.952 # [2] + 'm062x/6-31+g(d,p), software: gaussian': 0.979 # [3] + 'm062x/6-311+g(d,p), software: gaussian': 0.983 # [3] + 'm062x/6-311++g(d,p), software: gaussian': 0.983 # [3] + 'm062x/cc-pvtz, software: gaussian': 0.955 # [2] + 'm062x/aug-cc-pvdz, software: gaussian': 0.993 # [3] + 'm062x/aug-cc-pvtz, software: gaussian': 0.985 # [1] Table 3, [3] + 'm062x/def2tzvp, software: gaussian': 0.984 # [3] + 'm062x/def2qzvp, software: gaussian': 0.983 # [3] + 'm062x/def2tzvpp, software: gaussian': 0.983 # [1] Table 3, [3] + 'm08so/mg3s*, software: gaussian': 0.995 # [1] Table 3, taken as 'M08-SO/MG3S' + 'b97d3/def2msvp, software: gaussian': 1.014 # [4] + 'wb97xd/cc-pvtz, software: gaussian': 0.987 # [4] + 'wb97xd/aug-cc-pvtz, software: gaussian': 0.988 # [3], taken as 'ωB97X-D/maug-cc-pVTZ' + 'wb97xd/6-311++g(d,p), software: gaussian': 0.988 # [4] + 'wb97xd/def2svp, software: gaussian': 0.986 # [4] + 'wb97xd/def2tzvp, software: gaussian': 0.988 # [4] + 'wb97xd3/def2-tzvp, software: qchem': 0.984 # [4] + 'wb97m-v/def2-tzvpd, software: qchem': 1.002 # [4] + 'b2plypd3/cc-pvtz, software: gaussian': 0.993 # [4] + 'b2plypd3/aug-cc-pvtz, software: gaussian': 0.995 # [4] + 'b2plypd3/def2tzvp, software: gaussian': 0.995 # [4] + 'apfd/def2tzvp, software: gaussian': 0.993 # [4] + 'apfd/def2tzvpp, software: gaussian': 0.992 # [4] + 'mp2/cc-pvdz, software: gaussian': 0.953 # [2] + 'mp2/cc-pvtz, software: gaussian': 0.950 # [2] + 'mp2/cc-pvqz, software: gaussian': 0.962 # [2] + 'cbs-qb3, software: gaussian': 1.004 # 0.99 * 1.014, [5], the 0.99 value is the ZPE scale factor of CBS-QB3 + 'cbs-qb3-paraskevas, software: gaussian': 1.004 # Same as above, added for consistency with Arkane + 'ccsd/cc-pvdz, software: molpro': 0.947 # [2], taken as 'CCSD/cc-pVDZ' + 'ccsd(t)/cc-pvdz, software: molpro': 0.979 # [2] + 'ccsd(t)/cc-pvtz, software: molpro': 0.975 # [2] + 'ccsd(t)/cc-pvqz, software: molpro': 0.970 # [2] + 'ccsd(t)/aug-cc-pvdz, software: molpro': 0.963 # [2] + 'ccsd(t)/aug-cc-pvtz, software: molpro': 1.001 # [3] + 'ccsd(t)/aug-cc-pvqz, software: molpro': 0.975 # [2] + 'ccsd(t)/cc-pv(t+d)z, software: molpro': 0.965 # [2] + 'ccsd(t)-f12/cc-pvdz-f12, software: molpro': 0.997 # [3], taken as 'CCSD(T)-F12a/cc-pVDZ-F12' + 'ccsd(t)-f12/cc-pvtz-f12, software: molpro': 0.998 # [3], taken as 'CCSD(T)-F12a/cc-pVTZ-F12' + 'ccsd(t)-f12/cc-pvqz-f12, software: molpro': 0.998 # [3], taken as 'CCSD(T)-F12b/VQZF12//CCSD(T)-F12a/TZF' + 'ccsd(t)-f12/cc-pcvdz-f12, software: molpro': 0.997 # [3], taken as 'CCSD(T)-F12a/cc-pVDZ-F12' + 'ccsd(t)-f12/cc-pcvtz-f12, software: molpro': 0.998 # [3], taken as 'CCSD(T)-F12a/cc-pVTZ-F12' + 'ccsd(t)-f12/aug-cc-pvdz, software: molpro': 0.997 # [3], taken as 'CCSD(T)/cc-pVDZ' + 'ccsd(t)-f12/aug-cc-pvtz, software: molpro': 0.998 # [3], taken as CCSD(T)-F12a/cc-pVTZ-F12 + 'ccsd(t)-f12/aug-cc-pvqz, software: molpro': 0.998 # [3], taken as 'CCSD(T)-F12b/VQZF12//CCSD(T)-F12a/TZF' From c97b35c3b2800c0d186d379c546d1fc970b0a962 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Sat, 29 Jun 2024 00:49:58 +0300 Subject: [PATCH 03/12] Added assign_frequency_scale_factor() to Level replacing a call to Arkane --- arc/level.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/arc/level.py b/arc/level.py index 2b5dc7c525..5f9a865ee7 100644 --- a/arc/level.py +++ b/arc/level.py @@ -9,7 +9,6 @@ import arkane.encorr.data as arkane_data from arkane.encorr.bac import BAC -from arkane.encorr.corr import assign_frequency_scale_factor from arkane.modelchem import METHODS_THAT_REQUIRE_SOFTWARE, LevelOfTheory, standardize_name from arc.common import ARC_PATH, get_logger, get_ordered_intersection_of_two_lists, read_yaml_file @@ -59,7 +58,7 @@ def __init__(self, method_type: Optional[str] = None, software: Optional[str] = None, software_version: Optional[Union[int, float, str]] = None, - compatible_ess: Optional[List[str, ...]] = None, + compatible_ess: Optional[List[str]] = None, solvation_method: Optional[str] = None, solvent: Optional[str] = None, solvation_scheme_level: Optional[Level] = None, @@ -154,8 +153,6 @@ def __str__(self) -> str: for key, arg in self.args.items(): if key == 'keyword': str_ += f' {arg}' - if self.method_type is not None: - str_ += f' ({self.method_type})' return str_ def copy(self): @@ -573,3 +570,24 @@ def get_params_from_arkane_level_of_theory_as_str(arkane_level: str) -> Dict[str splits = arkane_level.split(f"{key}='") level_dict[key] = splits[1].split("'")[0] return level_dict + + +def assign_frequency_scale_factor(level: Union[str, Level]) -> Optional[int]: + """ + Assign a frequency scaling factor to a level of theory. + + Args: + level (Union[str, Level]): The level of theory. + + Returns: + Optional[int]: The frequency scaling factor. + """ + freq_scale_factors = read_yaml_file(os.path.join(ARC_PATH, 'data', 'freq_scale_factors.yml'))['freq_scale_factors'] + if isinstance(level, str): + if level in freq_scale_factors: + return freq_scale_factors[level] + level = Level(repr=level) + level_str = str(level) + if level_str in freq_scale_factors: + return freq_scale_factors[level_str] + return None From 320c4b8b1cf8d15a930950f27c090b7b71ad5e8d Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Sat, 29 Jun 2024 00:50:09 +0300 Subject: [PATCH 04/12] Tests: Level str and freq scale factor --- arc/level_test.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/arc/level_test.py b/arc/level_test.py index a1d9b68b0c..361d4e2b50 100644 --- a/arc/level_test.py +++ b/arc/level_test.py @@ -11,7 +11,7 @@ from arkane.modelchem import LevelOfTheory from arc.common import ARC_PATH, read_yaml_file -from arc.level import Level, get_params_from_arkane_level_of_theory_as_str +from arc.level import Level, assign_frequency_scale_factor, get_params_from_arkane_level_of_theory_as_str class TestLevel(unittest.TestCase): @@ -210,6 +210,36 @@ def test_determine_compatible_ess(self): level_2.determine_compatible_ess() self.assertEqual(sorted(level_2.compatible_ess), sorted(['gaussian', 'qchem', 'terachem'])) + def test_str(self): + """Test the __str__() method.""" + self.assertEqual(str(Level(method='HF', basis='6-31g')), 'hf/6-31g, software: gaussian') + self.assertEqual(str(Level(method='HF', basis='6-31+g(d,p)')), 'hf/6-31+g(d,p), software: gaussian') + self.assertEqual(str(Level(method='PM6')), 'pm6, software: gaussian') + self.assertEqual(str(Level(method='b3lyp', basis='6-311+g(d,p)')), 'b3lyp/6-311+g(d,p), software: gaussian') + self.assertEqual(str(Level(method='M062x', basis='Aug-cc-pvdz')), 'm062x/aug-cc-pvdz, software: gaussian') + self.assertEqual(str(Level(method='M062x', basis='Def2TZVP')), 'm062x/def2tzvp, software: gaussian') + self.assertEqual(str(Level(method='M06-2x', basis='Def2-TZVP')), 'm06-2x/def2-tzvp, software: qchem') + self.assertEqual(str(Level(method='wb97xd', basis='def2tzvp')), 'wb97xd/def2tzvp, software: gaussian') + self.assertEqual(str(Level(method='wb97m-v', basis='def2-tzvpd')), 'wb97m-v/def2-tzvpd, software: qchem') + self.assertEqual(str(Level(method='b2plypd3', basis='cc-pvtz')), 'b2plypd3/cc-pvtz, software: gaussian') + self.assertEqual(str(Level(method='apfd', basis='def2tzvp')), 'apfd/def2tzvp, software: gaussian') + self.assertEqual(str(Level(method='mp2', basis='cc-pvdz')), 'mp2/cc-pvdz, software: gaussian') + self.assertEqual(str(Level(method='CBS-QB3')), 'cbs-qb3, software: gaussian') + self.assertEqual(str(Level(method='CCSD(T)', basis='cc-pVTZ')), 'ccsd(t)/cc-pvtz, software: molpro') + self.assertEqual(str(Level(method='CCSD(T)-F12', basis='cc-pVTZ-F12')), 'ccsd(t)-f12/cc-pvtz-f12, software: molpro') + self.assertEqual(str(Level(method='wb97xd', basis='def2tzvp', solvation_method='smd', solvent='water')), + 'wb97xd/def2tzvp, solvation_method: smd, solvent: water, software: gaussian') + self.assertEqual(str(Level(basis='def2svp', compatible_ess=['gaussian', 'terachem'],method='wb97xd', + method_type='dft', software='gaussian')), 'wb97xd/def2svp, software: gaussian') + + def test_assign_frequency_scale_factor(self): + """Test the assign_frequency_scale_factor() method.""" + self.assertEqual(assign_frequency_scale_factor(Level(method='CCSD(T)', basis='cc-pvtz')), 0.975) + self.assertEqual(assign_frequency_scale_factor(Level(method='CCSD(T)-F12', basis='cc-pvtz-F12')), 0.998) + self.assertEqual(assign_frequency_scale_factor(Level(method='wb97xd', basis='Def2TZVP')), 0.988) + self.assertEqual(assign_frequency_scale_factor(Level(method='CBS-QB3')), 1.004) + self.assertEqual(assign_frequency_scale_factor(Level(method='PM6')), 1.093) + if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(verbosity=2)) From 3b6df82bda7dc3e19b53f27ef725ecb215ad5400 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Thu, 11 Jul 2024 14:01:09 +0300 Subject: [PATCH 05/12] Use Level.assign_frequency_scale_factor() in main Instead of Arkane's function --- arc/main.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/arc/main.py b/arc/main.py index c675933bc3..765ce85200 100644 --- a/arc/main.py +++ b/arc/main.py @@ -18,7 +18,6 @@ from IPython.display import display from typing import Dict, List, Optional, Tuple, Union -from arkane.encorr.corr import assign_frequency_scale_factor from rmgpy.reaction import Reaction from rmgpy.species import Species @@ -37,7 +36,7 @@ ) from arc.exceptions import InputError, SettingsError, SpeciesError from arc.imports import settings -from arc.level import Level +from arc.level import Level, assign_frequency_scale_factor from arc.job.factory import _registered_job_adapters from arc.job.ssh import SSHClient from arc.processor import process_arc_project @@ -906,16 +905,12 @@ def check_freq_scaling_factor(self): freq_level = self.composite_method if self.composite_method is not None \ else self.freq_level if self.freq_level is not None else None if freq_level is not None: - arkane_freq_lot = freq_level.to_arkane_level_of_theory(variant='freq') - if arkane_freq_lot is not None: - # Arkane has this harmonic frequencies scaling factor. - self.freq_scale_factor = assign_frequency_scale_factor(level_of_theory=arkane_freq_lot) - else: - logger.info(f'Could not determine the harmonic frequencies scaling factor for ' - f'{arkane_freq_lot} from Arkane.') + self.freq_scale_factor = assign_frequency_scale_factor(level=freq_level) + if self.freq_scale_factor is None: + logger.info(f'Could not determine the harmonic frequencies scaling factor for {freq_level}.') if self.calc_freq_factor: logger.info("Calculating it using Truhlar's method.") - logger.warning("This proceedure normally spawns QM jobs for various small species " + logger.warning("This procedure normally spawns QM jobs for various small species " "not directly asked for by the user.\n\n") self.freq_scale_factor = determine_scaling_factors(levels=[freq_level], ess_settings=self.ess_settings, From 29ac9f783f4c1ea3800964f7f56928d48bc75734 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Thu, 27 Jun 2024 23:13:25 +0300 Subject: [PATCH 06/12] Don't call Arkane's assign_frequency_scale_factor() in Level instead, just return the freq variant with the software info (Arkane should be able to deal with it and remove the software info if not needed) --- arc/level.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arc/level.py b/arc/level.py index 5f9a865ee7..aa5772c6d7 100644 --- a/arc/level.py +++ b/arc/level.py @@ -395,12 +395,7 @@ def to_arkane_level_of_theory(self, var_1 = None if variant == 'freq': - # if not found, the factor is set to exactly 1 - if assign_frequency_scale_factor(level_of_theory=var_1) != 1: - return var_1 - if assign_frequency_scale_factor(level_of_theory=var_2) != 1: - return var_2 - return None + return var_2 if variant == 'AEC': try: From b7144fd18c535f578e3c8f61f10474056eed7adb Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Thu, 27 Jun 2024 23:19:07 +0300 Subject: [PATCH 07/12] Updated freq scale factor reporting recommendation --- arc/utils/scale.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/arc/utils/scale.py b/arc/utils/scale.py index d5232095bf..a97aea464f 100644 --- a/arc/utils/scale.py +++ b/arc/utils/scale.py @@ -222,9 +222,8 @@ def summarize_results(lambda_zpes: list, with open(info_file_path, 'w') as f: f.write(HEADER) - database_text = '\n\n\nYou may copy-paste the following harmonic frequency scaling factor(s) to ' \ - 'the RMG-database repository\n' \ - '(under the `freq_dict` in RMG-database/input/quantum_corrections/data.py):\n' + database_text = '\n\n\nYou may copy-paste the computed harmonic frequency scaling factor(s) to ARC ' \ + '(under the `freq_dict` in ARC/data/freq_scale_factors.yml):\n' database_formats = list() harmonic_freq_scaling_factors = list() for lambda_zpe, level, zpe_dict, execution_time\ @@ -233,13 +232,6 @@ def summarize_results(lambda_zpes: list, fundamental_freq_scaling_factor = lambda_zpe * 0.974 harmonic_freq_scaling_factors.append(fundamental_freq_scaling_factor) unconverged = [key for key, val in zpe_dict.items() if val is None] - arkane_level = level.to_arkane_level_of_theory().simple() - arkane_level_str = f"LevelOfTheory(method='{level.method}'" - if arkane_level.basis is not None: - arkane_level_str += f",basis='{level.basis}'" - if arkane_level.software is not None: - arkane_level_str += f",software='{level.software}'" - arkane_level_str += f")" text = f'\n\nLevel of theory: {level}\n' if unconverged: @@ -250,7 +242,7 @@ def summarize_results(lambda_zpes: list, text += f'(execution time: {execution_time})\n' logger.info(text) f.write(text) - database_formats.append(f""" "{arkane_level_str}": {harmonic_freq_scaling_factor:.3f}, # [4]\n""") + database_formats.append(f""" '{level}': {harmonic_freq_scaling_factor:.3f}, # [4]\n""") logger.info(database_text) f.write(database_text) for database_format in database_formats: From 180122e5641d2ea9d436e175161134d03cc5f179 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Thu, 27 Jun 2024 23:23:31 +0300 Subject: [PATCH 08/12] Tests: Adaptations to scale test --- arc/utils/scale_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arc/utils/scale_test.py b/arc/utils/scale_test.py index 313e9bca0b..fb8f1b9602 100644 --- a/arc/utils/scale_test.py +++ b/arc/utils/scale_test.py @@ -85,15 +85,15 @@ def test_summarize_results(self): with open(info_file_path, 'r') as f: lines = f.readlines() self.assertIn('CITATIONS:\n', lines) - self.assertIn('Level of theory: cbs-qb3, software: gaussian (composite)\n', lines) - self.assertIn('Level of theory: b2plypd3/def2tzvp, software: gaussian (dft)\n', lines) + self.assertIn('Level of theory: cbs-qb3, software: gaussian\n', lines) + self.assertIn('Level of theory: b2plypd3/def2tzvp, software: gaussian\n', lines) self.assertIn('The following species from the standard set did not converge at this level:\n', lines) self.assertIn(" ['CO2']\n", lines) self.assertIn('Scale Factor for Fundamental Frequencies = 0.955\n', lines) self.assertIn('Scale Factor for Harmonic Frequencies = 0.994\n', lines) - self.assertIn('You may copy-paste the following harmonic frequency scaling factor(s) to the RMG-database repository\n', lines) - self.assertIn(""" "LevelOfTheory(method='cbs-qb3')": 0.963, # [4]\n""", lines) - self.assertIn(""" "LevelOfTheory(method='b2plypd3',basis='def2tzvp')": 0.994, # [4]\n""", lines) + self.assertIn('You may copy-paste the computed harmonic frequency scaling factor(s) to ARC (under the `freq_dict` in ARC/data/freq_scale_factors.yml):\n', lines) + self.assertIn(" 'cbs-qb3, software: gaussian': 0.963, # [4]\n", lines) + self.assertIn(" 'b2plypd3/def2tzvp, software: gaussian': 0.994, # [4]\n", lines) self.assertIn('Scaling factors calculation for 2 levels of theory completed (elapsed time: 8.5).\n', lines) def test_get_species_list(self): From 6853c27c58854404a2efbb953ae5bba8cebabfef Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Fri, 28 Jun 2024 07:00:05 +0300 Subject: [PATCH 09/12] Tests: Adaptations to Level tests --- arc/level_test.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arc/level_test.py b/arc/level_test.py index 361d4e2b50..b33f940d60 100644 --- a/arc/level_test.py +++ b/arc/level_test.py @@ -29,7 +29,7 @@ def test_level(self): self.assertEqual(level_1.dispersion, 'gd3bj') self.assertEqual(level_1.software, 'gaussian') self.assertEqual(str(level_1), - "b3lyp/def2tzvp, auxiliary_basis: aug-def2-svp, dispersion: gd3bj, software: gaussian (dft)") + "b3lyp/def2tzvp, auxiliary_basis: aug-def2-svp, dispersion: gd3bj, software: gaussian") self.assertEqual(level_1.simple(), "b3lyp/def2tzvp") def test_deduce_software(self): @@ -99,13 +99,13 @@ def test_build(self): self.assertEqual(level_1.method, 'wb97xd') self.assertEqual(level_1.basis, 'def2-tzvp') self.assertEqual(level_1.method_type, 'dft') - self.assertEqual(str(level_1), 'wb97xd/def2-tzvp, software: gaussian (dft)') + self.assertEqual(str(level_1), 'wb97xd/def2-tzvp, software: gaussian') level_2 = Level(repr='CBS-QB3') self.assertEqual(level_2.method, 'cbs-qb3') self.assertIsNone(level_2.basis) self.assertEqual(level_2.software, 'gaussian') self.assertEqual(level_2.method_type, 'composite') - self.assertEqual(str(level_2), 'cbs-qb3, software: gaussian (composite)') + self.assertEqual(str(level_2), 'cbs-qb3, software: gaussian') self.assertEqual(level_2.simple(), 'cbs-qb3') level_3 = Level(repr={'method': 'DLPNO-CCSD(T)', 'basis': 'def2-TZVp', @@ -123,8 +123,7 @@ def test_build(self): self.assertEqual(level_3.solvation_scheme_level.basis, 'def2-tzvp') self.assertEqual(str(level_3), "dlpno-ccsd(t)/def2-tzvp, auxiliary_basis: def2-tzvp/c, solvation_method: smd, " - "solvent: water, solvation_scheme_level: 'apfd/def2-tzvp, software: gaussian (dft)', " - "software: orca (wavefunction)") + "solvent: water, solvation_scheme_level: 'apfd/def2-tzvp, software: gaussian', software: orca") def test_to_arkane(self): """Test converting Level to LevelOfTheory""" @@ -139,7 +138,7 @@ def test_to_arkane(self): self.assertEqual(level_2.to_arkane_level_of_theory(variant='AEC'), LevelOfTheory(method='cbs-qb3', software='gaussian')) self.assertEqual(level_2.to_arkane_level_of_theory(variant='freq'), - LevelOfTheory(method='cbs-qb3', software='gaussian')) + LevelOfTheory(method='cbs-qb3')) self.assertEqual(level_2.to_arkane_level_of_theory(variant='BAC'), LevelOfTheory(method='cbs-qb3', software='gaussian')) self.assertIsNone(level_2.to_arkane_level_of_theory(variant='BAC', bac_type='m')) # might change in the future From b0241239249e96d71ccfabb9b133aed4cf47933a Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Fri, 28 Jun 2024 07:00:58 +0300 Subject: [PATCH 10/12] Tests: Adaptations to main tests --- arc/main_test.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/arc/main_test.py b/arc/main_test.py index c25357de97..6e39d9e227 100644 --- a/arc/main_test.py +++ b/arc/main_test.py @@ -221,23 +221,22 @@ def test_check_project_name(self): def test_determine_model_chemistry_and_freq_scale_factor(self): """Test determining the model chemistry and the frequency scaling factor""" arc0 = ARC(project='arc_model_chemistry_test', level_of_theory='CBS-QB3') - self.assertEqual(str(arc0.arkane_level_of_theory), "cbs-qb3, software: gaussian (composite)") - self.assertEqual(arc0.freq_scale_factor, 1.00386) # 0.99 * 1.014 = 1.00386 + self.assertEqual(str(arc0.arkane_level_of_theory), "cbs-qb3, software: gaussian") + self.assertEqual(arc0.freq_scale_factor, 1.004) - arc1 = ARC(project='arc_model_chemistry_test', - level_of_theory='cbs-qb3-paraskevas') - self.assertEqual(str(arc1.arkane_level_of_theory), 'cbs-qb3-paraskevas, software: gaussian (composite)') - self.assertEqual(arc1.freq_scale_factor, 1.00386) # 0.99 * 1.014 = 1.00386 + arc1 = ARC(project='arc_model_chemistry_test', level_of_theory='cbs-qb3-paraskevas') + self.assertEqual(str(arc1.arkane_level_of_theory), 'cbs-qb3-paraskevas, software: gaussian') + self.assertEqual(arc1.freq_scale_factor, 1.004) self.assertEqual(arc1.bac_type, 'p') arc2 = ARC(project='arc_model_chemistry_test', - level_of_theory='ccsd(t)-f12/cc-pvtz-f12//m06-2x/cc-pvtz') - self.assertEqual(str(arc2.arkane_level_of_theory), 'ccsd(t)-f12/cc-pvtz-f12, software: molpro (wavefunction)') + level_of_theory='ccsd(t)-f12/cc-pvtz-f12//m062x/cc-pvtz') + self.assertEqual(str(arc2.arkane_level_of_theory), 'ccsd(t)-f12/cc-pvtz-f12, software: molpro') self.assertEqual(arc2.freq_scale_factor, 0.955) arc3 = ARC(project='arc_model_chemistry_test', sp_level='ccsd(t)-f12/cc-pvtz-f12', opt_level='wb97xd/def2tzvp') - self.assertEqual(str(arc3.arkane_level_of_theory), 'ccsd(t)-f12/cc-pvtz-f12, software: molpro (wavefunction)') + self.assertEqual(str(arc3.arkane_level_of_theory), 'ccsd(t)-f12/cc-pvtz-f12, software: molpro') self.assertEqual(arc3.freq_scale_factor, 0.988) def test_determine_model_chemistry_for_job_types(self): @@ -279,7 +278,7 @@ def test_determine_model_chemistry_for_job_types(self): self.assertEqual(arc2.composite_method.simple(), 'cbs-qb3') # Test deduce levels from level of theory specification - arc3 = ARC(project='test', level_of_theory='ccsd(t)-f12/cc-pvtz-f12//wb97m-v/def2tzvpd') + arc3 = ARC(project='test', level_of_theory='ccsd(t)-f12/cc-pvtz-f12//wb97m-v/def2tzvpd', freq_scale_factor=1) self.assertEqual(arc3.opt_level.simple(), 'wb97m-v/def2tzvpd') self.assertEqual(arc3.freq_level.simple(), 'wb97m-v/def2tzvpd') self.assertEqual(arc3.sp_level.simple(), 'ccsd(t)-f12/cc-pvtz-f12') @@ -315,10 +314,10 @@ def test_determine_model_chemistry_for_job_types(self): calc_freq_factor=False, compute_thermo=False) self.assertEqual(arc9.opt_level.simple(), 'wb97xd/def2tzvp') self.assertEqual(str(arc9.freq_level), 'b3lyp/g/cc-pvdz(fi/sf/fw), auxiliary_basis: def2-svp/c, ' - 'dispersion: def2-tzvp/c, software: gaussian (dft)') + 'dispersion: def2-tzvp/c, software: gaussian') self.assertEqual(str(arc9.sp_level), 'dlpno-ccsd(t)-f12/cc-pvtz-f12, auxiliary_basis: aug-cc-pvtz/c cc-pvtz-f12-cabs, ' - 'software: orca (wavefunction)') + 'software: orca') # Test using default frequency and orbital level for composite job, also forbid rotors job arc10 = ARC(project='test', composite_method='cbs-qb3', calc_freq_factor=False, From 5187cbe1e320f3ef8dc61f6f12f5bb9fd75e9392 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Fri, 28 Jun 2024 19:26:45 +0300 Subject: [PATCH 11/12] Tests: Adaptations to Reaction tests --- arc/testing/reactions/methanoate_hydrolysis/input_1.yml | 2 ++ arc/testing/reactions/methanoate_hydrolysis/input_2.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arc/testing/reactions/methanoate_hydrolysis/input_1.yml b/arc/testing/reactions/methanoate_hydrolysis/input_1.yml index b8f31a088f..7e207f255e 100644 --- a/arc/testing/reactions/methanoate_hydrolysis/input_1.yml +++ b/arc/testing/reactions/methanoate_hydrolysis/input_1.yml @@ -39,6 +39,8 @@ job_types: freq: true sp: true +freq_scale_factor: 1.0 + species: - label: 'H2O' smiles: O diff --git a/arc/testing/reactions/methanoate_hydrolysis/input_2.yml b/arc/testing/reactions/methanoate_hydrolysis/input_2.yml index b8f31a088f..7e207f255e 100644 --- a/arc/testing/reactions/methanoate_hydrolysis/input_2.yml +++ b/arc/testing/reactions/methanoate_hydrolysis/input_2.yml @@ -39,6 +39,8 @@ job_types: freq: true sp: true +freq_scale_factor: 1.0 + species: - label: 'H2O' smiles: O From 6109395a9b1ca821a14e0cff512ffac559896464 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Fri, 5 Jul 2024 22:52:44 +0300 Subject: [PATCH 12/12] Check if level.method is not empty before splitting them as str in ARC.as_dict() to avoid an IndexError --- arc/main.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arc/main.py b/arc/main.py index 765ce85200..bc33c00d1f 100644 --- a/arc/main.py +++ b/arc/main.py @@ -503,7 +503,8 @@ def as_dict(self) -> dict: if not isinstance(self.freq_level, (dict, str)) else self.freq_level if self.freq_scale_factor is not None: restart_dict['freq_scale_factor'] = self.freq_scale_factor - if self.irc_level is not None and str(self.irc_level).split()[0] != default_levels_of_theory['irc']: + if self.irc_level is not None and len(self.irc_level.method) \ + and str(self.irc_level).split()[0] != default_levels_of_theory['irc']: restart_dict['irc_level'] = self.irc_level.as_dict() \ if not isinstance(self.irc_level, (dict, str)) else self.irc_level if self.keep_checks: @@ -520,7 +521,8 @@ def as_dict(self) -> dict: if self.opt_level is not None and str(self.opt_level).split()[0] != default_levels_of_theory['opt']: restart_dict['opt_level'] = self.opt_level.as_dict() \ if not isinstance(self.opt_level, (dict, str)) else self.opt_level - if self.orbitals_level is not None and str(self.orbitals_level).split()[0] != default_levels_of_theory['orbitals']: + if self.orbitals_level is not None and len(self.orbitals_level.method) \ + and str(self.orbitals_level).split()[0] != default_levels_of_theory['orbitals']: restart_dict['orbitals_level'] = self.orbitals_level.as_dict() \ if not isinstance(self.orbitals_level, (dict, str)) else self.orbitals_level if self.output: @@ -532,10 +534,12 @@ def as_dict(self) -> dict: restart_dict['reactions'] = [rxn.as_dict() for rxn in self.reactions] if self.running_jobs: restart_dict['running_jobs'] = self.running_jobs - if self.scan_level is not None and str(self.scan_level).split()[0] != default_levels_of_theory['scan']: + if self.scan_level is not None and len(self.scan_level.method) \ + and str(self.scan_level).split()[0] != default_levels_of_theory['scan']: restart_dict['scan_level'] = self.scan_level.as_dict() \ if not isinstance(self.scan_level, (dict, str)) else self.scan_level - if self.sp_level is not None and str(self.sp_level).split()[0] != default_levels_of_theory['sp']: + if self.sp_level is not None and len(self.sp_level.method) \ + and str(self.sp_level).split()[0] != default_levels_of_theory['sp']: restart_dict['sp_level'] = self.sp_level.as_dict() \ if not isinstance(self.sp_level, (dict, str)) else self.sp_level restart_dict['species'] = [spc.as_dict() for spc in self.species]