Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 42 additions & 26 deletions arkane/encorr/bac.py
Original file line number Diff line number Diff line change
Expand Up @@ -814,35 +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:]):
if repr(self.level_of_theory) in line2:
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)
Expand Down
9 changes: 8 additions & 1 deletion arkane/encorr/bacTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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')

Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion documentation/source/users/arkane/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down