From e4ea2a86ea256e8f4bd1481dbf8e92eb2237798a Mon Sep 17 00:00:00 2001 From: Kevin Spiekermann Date: Thu, 8 Jul 2021 16:47:25 -0400 Subject: [PATCH 1/4] Update documentation to reflect additions in RMG-database --- documentation/source/users/arkane/input.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/source/users/arkane/input.rst b/documentation/source/users/arkane/input.rst index 9bc627080c..c66348f730 100644 --- a/documentation/source/users/arkane/input.rst +++ b/documentation/source/users/arkane/input.rst @@ -125,7 +125,8 @@ Model Chemistry AEC BC SOC Freq Scale Supp ``'CCSD-F12/cc-pVDZ-F12'`` v v v (0.947) H, C, N, O ``'CCSD(T)-F12/cc-pVDZ-F12_H-TZ'`` v v H, C, N, O ``'CCSD(T)-F12/cc-pVDZ-F12_H-QZ'`` v v H, C, N, O -``'CCSD(T)-F12/cc-pVnZ-F12'``, *n = D,T,Q* v v v v H, C, N, O, S +``'CCSD(T)-F12/cc-pVnZ-F12'``, *n = D,T* v v v v H, C, N, O, F, S, Cl +``'CCSD(T)-F12/cc-pVQZ-F12'`` v v v v H, C, N, O, S ``'CCSD(T)-F12/cc-pVDZ-F12_noscale'`` v v H, C, N, O ``'CCSD(T)-F12/cc-pCVnZ-F12'``, *n = D,T,Q* v v v H, C, N, O ``'CCSD(T)-F12/aug-cc-pVnZ'``, *n = D,T,Q* v v v H, C, N, O, S From 1ccbb2f3cd026871c1a17df6fd671e513bc83208 Mon Sep 17 00:00:00 2001 From: Kevin Spiekermann Date: Sun, 11 Jul 2021 22:00:23 -0400 Subject: [PATCH 2/4] BugFix: Allow BACs to properly overwrite composite LoT Previously, the code would search for LoT while iterating over lines and overwrite the first instance of the LoT. However, this does not account for partial matches, such as within a Composite LoT --- arkane/encorr/bac.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arkane/encorr/bac.py b/arkane/encorr/bac.py index d459d9ffd0..1ea9a17220 100644 --- a/arkane/encorr/bac.py +++ b/arkane/encorr/bac.py @@ -822,7 +822,15 @@ def write_to_database(self, overwrite: bool = False, alternate_path: str = None) # Does not overwrite comments del_idx_start = del_idx_end = None for j, line2 in enumerate(lines[i:]): - if repr(self.level_of_theory) in line2: + proceed = False + if 'Composite' not in repr(self.level_of_theory) \ + and repr(self.level_of_theory) in line2 and 'Composite' not in line2: + proceed = True + elif 'Composite' in repr(self.level_of_theory) \ + and repr(self.level_of_theory) in line2: + proceed = True + + if proceed: del_idx_start = i + j del_idx_end = None elif line2.rstrip() == ' },': # Can't have comment after final brace From b39d58c5743be639438c704c54d08c49a9aa0468 Mon Sep 17 00:00:00 2001 From: Kevin Spiekermann Date: Sun, 11 Jul 2021 21:57:25 -0400 Subject: [PATCH 3/4] Tests: Update BAC testing to test overwriting composite LoT --- arkane/encorr/bacTest.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arkane/encorr/bacTest.py b/arkane/encorr/bacTest.py index 02dae4d2cf..34d18a7712 100644 --- a/arkane/encorr/bacTest.py +++ b/arkane/encorr/bacTest.py @@ -48,7 +48,7 @@ from arkane.encorr.data import BACDataset, BOND_SYMBOLS, _pybel_to_rmg from arkane.encorr.reference import ReferenceDatabase from arkane.exceptions import BondAdditivityCorrectionError -from arkane.modelchem import LevelOfTheory +from arkane.modelchem import LevelOfTheory, CompositeLevelOfTheory class TestBAC(unittest.TestCase): @@ -59,6 +59,7 @@ class TestBAC(unittest.TestCase): @classmethod def setUpClass(cls): cls.lot_get = LevelOfTheory(method='CCSD(T)-F12', basis='cc-pVTZ-F12', software='Molpro') + cls.lot_get_composite = CompositeLevelOfTheory(freq=LevelOfTheory(method='wb97xd3',basis='def2tzvp',software='qchem'),energy=LevelOfTheory(method='ccsd(t)f12',basis='ccpvtzf12',software='molpro')) cls.lot_fit = LevelOfTheory(method='wB97M-V', basis='def2-TZVPD', software='Q-Chem') cls.lot_nonexisting = LevelOfTheory('notamethod') @@ -242,6 +243,12 @@ def test_write_to_database(self): spec.loader.exec_module(module) # Load data as module self.assertEqual(self.bac.bacs, module.pbac[repr(self.bac.level_of_theory)]) + # Check that existing Composite Petersson BACs can be overwritten + self.bac.level_of_theory = self.lot_get_composite + self.bac.write_to_database(overwrite=True, alternate_path=tmp_datafile_path) + spec.loader.exec_module(module) # Load data as module + self.assertEqual(self.bac.bacs, module.pbac[repr(self.bac.level_of_theory)]) + # Check that new Petersson BACs can be written self.bac.level_of_theory = self.lot_nonexisting self.bac.bacs = self.tmp_petersson_params From dcd53c738a0322dc1edf8eabd2aa94a2a252f293 Mon Sep 17 00:00:00 2001 From: Xiaorui Dong Date: Wed, 28 Jul 2021 17:11:50 -0400 Subject: [PATCH 4/4] Improve the readability of `write_to_database` --- arkane/encorr/bac.py | 76 ++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/arkane/encorr/bac.py b/arkane/encorr/bac.py index 1ea9a17220..d1472860aa 100644 --- a/arkane/encorr/bac.py +++ b/arkane/encorr/bac.py @@ -814,43 +814,51 @@ def write_to_database(self, overwrite: bool = False, alternate_path: str = None) has_entries = bool(data.mbac) if self.bac_type == 'm' else bool(data.pbac) # Add new BACs to file without changing existing formatting + # First: find the BACs dict in the file for i, line in enumerate(lines): if keyword in line: - if has_entries: - if self.level_of_theory in bac_dict: - if overwrite: - # Does not overwrite comments - del_idx_start = del_idx_end = None - for j, line2 in enumerate(lines[i:]): - proceed = False - if 'Composite' not in repr(self.level_of_theory) \ - and repr(self.level_of_theory) in line2 and 'Composite' not in line2: - proceed = True - elif 'Composite' in repr(self.level_of_theory) \ - and repr(self.level_of_theory) in line2: - proceed = True - - if proceed: - del_idx_start = i + j - del_idx_end = None - elif line2.rstrip() == ' },': # Can't have comment after final brace - del_idx_end = i + j + 1 - if del_idx_start is not None and del_idx_end is not None: - if (lines[del_idx_start - 1].lstrip().startswith('#') - or lines[del_idx_end + 1].lstrip().startswith('#')): - logging.warning('There may be left over comments from previous BACs') - lines[del_idx_start:del_idx_end] = bacs_formatted - break - else: - raise IOError( - f'{self.level_of_theory} already exists. Set `overwrite` to True.' - ) - else: - lines[(i+1):(i+1)] = ['\n'] + bacs_formatted - else: - lines[i] = f'{keyword} = {{\n' - lines[(i+1):(i+1)] = ['\n'] + bacs_formatted + ['\n}\n'] break + else: + # 'pbac' and 'mbac' should both be found at `data_path` + raise RuntimeError(f'Keyword "{keyword} is not found in the data file. ' + f'Please check the database file at {data_path} and ' + f'make sure an up-to-date RMG-database branch is used.') + + # Second: Write the BACs block into the BACs dict + # Does not overwrite comments + if self.level_of_theory in bac_dict and overwrite: + del_idx_start = del_idx_end = None + lot_repr = repr(self.level_of_theory) + for j, line2 in enumerate(lines[i:]): + if lot_repr in line2 and 'Composite' not in lot_repr and 'Composite' not in line2: + del_idx_start = i + j + elif lot_repr in line2 and 'Composite' in lot_repr: + del_idx_start = i + j + + if del_idx_start is not None and line2.rstrip() == ' },': # Can't have comment after final brace + del_idx_end = i + j + 1 + if (lines[del_idx_start - 1].lstrip().startswith('#') + or lines[del_idx_end + 1].lstrip().startswith('#')): + logging.warning('There may be left over comments from previous BACs') + lines[del_idx_start:del_idx_end] = bacs_formatted + break + + # Check if the entry is successfully inserted to the `lines` + if del_idx_start is None or del_idx_end is None: + raise RuntimeError(f'The script cannot identify the corresponding block for the given BACs. ' + f'It is possible that the database file at {data_path} is not correctly ' + f'formatted. Please check the file.') + + elif self.level_of_theory in bac_dict and not overwrite: + raise IOError( + f'{self.level_of_theory} already exists. Set `overwrite` to True.' + ) + else: + # Either empty BACs dict or adding BACs for a new level of theory + if not has_entries and '}' in lines[i]: # Empty BACs dict + lines[i] = f'{keyword} = {{\n' + lines[(i+1):(i+1)] = ['\n}\n'] + lines[(i+1):(i+1)] = ['\n'] + bacs_formatted with open(data_path if alternate_path is None else alternate_path, 'w') as f: f.writelines(lines)