Skip to content

Commit

Permalink
Merge pull request #160 from ReactionMechanismGenerator/rec_libs
Browse files Browse the repository at this point in the history
Added auto-completion for RMG thermo and kinetics libraries based on the chemistry set
  • Loading branch information
alongd authored Nov 1, 2024
2 parents 2dbc42a + 20ac269 commit 2d7c1ca
Show file tree
Hide file tree
Showing 15 changed files with 321 additions and 60 deletions.
153 changes: 153 additions & 0 deletions data/libraries.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Recommended RMG libraries per application

primary:
thermo:
- primaryThermoLibrary
- BurkeH2O2
- Spiekermann_refining_elementary_reactions
- thermo_DFT_CCSDTF12_BAC
- DFT_QCI_thermo
- CBS_QB3_1dHR
kinetics:
- primaryH2O2

nitrogen:
thermo:
- NH3
- NitrogenCurran
- CHON_G4
- CN
- NOx2018
- name: primaryNS
credence: low
- name: CHN
credence: low
- name: CHON
credence: low
- name: BurcatNS
credence: low
kinetics:
- primaryNitrogenLibrary
- HydrazinePDep
- Ethylamine

sulfur:
thermo:
- name: primaryNS
credence: low
- name: SulfurGlarborgH2S
credence: low
- name: SulfurGlarborgBozzeli
credence: low
- name: BurcatNS
credence: low
kinetics:
- primarySulfurLibrary
- Sulfur/DMDS
- Sulfur/DMS

combustion:
thermo:
- FFCM1(-)
- NOx2018
- name: CHO
credence: low
kinetics:
- FFCM1(-)
- 2006_Joshi_OH_CO
- 2005_Senosiain_OH_C2H2
- NOx2018

CH_pyrolysis:
thermo:
- NOx2018
- Butadiene_Dimerization
- C10H11
- s3_5_7_ane
- Fulvene_H
- naphthalene_H
- vinylCPD_H
- Lai_Hexylbenzene
- Narayanaswamy
- SABIC_aromatics_1dHR_extended
- SABIC_aromatics_1dHR
- SABIC_aromatics
- heavy_oil_ccsdtf12_1dHR
- bio_oil
- Chernov
- CurranPentane
- Klippenstein_Glarborg2016
- name: CH
credence: low
kinetics:
- 2001_Tokmakov_H_Toluene_to_CH3_Benzene
- 2003_Miller_Propargyl_Recomb_High_P
- 2009_Sharma_C5H5_CH3_highP
- 2015_Buras_C2H3_C4H6_highP
- Butadiene_Dimerization
- C10H11
- C12H11_pdep
- C2H2_init
- C6H5_C4H4_Mebel
- Fulvene_H
- Mebel_Naphthyl
- Mebel_C6H5_C2H2
- biCPD_H_shift
- c-C5H5_CH3_Sharma
- fascella
- kislovB
- naphthalene_H
- vinylCPD_H
- First_to_Second_Aromatic_Ring/2005_Ismail_C6H5_C4H6_highP
- First_to_Second_Aromatic_Ring/2012_Matsugi_C3H3_C7H7_highP
- First_to_Second_Aromatic_Ring/2016_Mebel_C10H9_highP
- First_to_Second_Aromatic_Ring/2016_Mebel_C9H9_highP
- First_to_Second_Aromatic_Ring/2016_Mebel_Indene_CH3_highP
- First_to_Second_Aromatic_Ring/2017_Buras_C6H5_C3H6_highP
- First_to_Second_Aromatic_Ring/2017_Mebel_C6H4C2H_C2H2_highP
- First_to_Second_Aromatic_Ring/2017_Mebel_C6H5C2H2_C2H2_highP
- First_to_Second_Aromatic_Ring/2017_Mebel_C6H5_C2H2_highP
- First_to_Second_Aromatic_Ring/2017_Mebel_C6H5_C4H4_highP
- First_to_Second_Aromatic_Ring/phenyl_diacetylene_effective
- Aromatics_high_pressure/C10H10_1
- Aromatics_high_pressure/C10H10_2
- Aromatics_high_pressure/C10H10_H_abstraction
- Aromatics_high_pressure/C10H11_1
- Aromatics_high_pressure/C10H11_2
- Aromatics_high_pressure/C10H11_3
- Aromatics_high_pressure/C10H11_4
- Aromatics_high_pressure/C10H7
- Aromatics_high_pressure/C10H8_H_abstraction_H_recomb
- Aromatics_high_pressure/C10H9_1
- Aromatics_high_pressure/C10H9_2
- Aromatics_high_pressure/C10H9_3
- Aromatics_high_pressure/C10H9_4
- Aromatics_high_pressure/C12H10_1
- Aromatics_high_pressure/C12H10_2
- Aromatics_high_pressure/C12H10_H_abstraction
- Aromatics_high_pressure/C12H11
- Aromatics_high_pressure/C12H8_H_abstraction
- Aromatics_high_pressure/C12H9
- Aromatics_high_pressure/C14H10_H_abstraction_H_recomb
- Aromatics_high_pressure/C14H11_1
- Aromatics_high_pressure/C14H11_2
- Aromatics_high_pressure/C14H11_3
- Aromatics_high_pressure/C14H11_4
- Aromatics_high_pressure/C14H9
- Aromatics_high_pressure/C16H11
- Aromatics_high_pressure/C7H8
- Aromatics_high_pressure/C7H8_H_abstraction
- Aromatics_high_pressure/C7H9
- Aromatics_high_pressure/C8H6_H_abstraction
- Aromatics_high_pressure/C8H7
- Aromatics_high_pressure/C8H8_H_abstraction
- Aromatics_high_pressure/C8H9
- Aromatics_high_pressure/C9H10_H_abstraction
- Aromatics_high_pressure/C9H11
- Aromatics_high_pressure/C9H7
- Aromatics_high_pressure/C9H8_1
- Aromatics_high_pressure/C9H8_2
- Aromatics_high_pressure/C9H8_H_abstraction
- Aromatics_high_pressure/C9H9_1
- Aromatics_high_pressure/C9H9_2

6 changes: 4 additions & 2 deletions examples/commented/input.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ rmg:

# database (a required block)
database:
thermo_libraries: ['BurkeH2O2', 'DFT_QCI_thermo', 'primaryThermoLibrary', 'CBS_QB3_1dHR'] # *required*, can be an empty list
kinetics_libraries: ['BurkeH2O2inN2', 'NOx2018', 'Klippenstein_Glarborg2016'] # *required*, can be an empty list
thermo_libraries: ['BurkeH2O2', 'DFT_QCI_thermo', 'primaryThermoLibrary', 'CBS_QB3_1dHR'] # Can be None for auto-completion
kinetics_libraries: ['BurkeH2O2inN2', 'NOx2018', 'Klippenstein_Glarborg2016'] # Can be None for auto-completion
chemistry_sets: ['primary', 'nitrogen', 'combustion'] # The chemistry systems for which thermo and kinetics libraries will be loaded. Can be None to avoid auto-completion
use_low_credence_libraries: False # Whether to use low credence libraries during auto-completion, default: ``False``
transport_libraries: ['PrimaryTransportLibrary', 'OneDMinN2', 'NOx2018', 'GRI-Mech'] # optional, default: ['PrimaryTransportLibrary', 'OneDMinN2', 'NOx2018', 'GRI-Mech']
seed_mechanisms: [] # optional, default: []
kinetics_depositories: default # optional, default: 'default'
Expand Down
5 changes: 3 additions & 2 deletions t3/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
VERSION = '0.1.0'

t3_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) # absolute path to the T3 folder
DATA_BASE_PATH = os.path.join(t3_path, 'tests', 'data')
SIMULATE_DATA_BASE_PATH = os.path.join(t3_path, 'tests', 'test_simulate_adapters', 'data')
DATA_BASE_PATH = os.path.join(t3_path, 'data')
TEST_DATA_BASE_PATH = os.path.join(t3_path, 'tests', 'data')
SIMULATE_TEST_DATA_BASE_PATH = os.path.join(t3_path, 'tests', 'test_simulate_adapters', 'data')
EXAMPLES_BASE_PATH = os.path.join(t3_path, 'examples')
SCRATCH_BASE_PATH = os.path.join(t3_path, 'tests', 'scratch')
IPYTHON_SIMULATOR_EXAMPLES_PATH = os.path.join(t3_path, 'ipython', 'simulator_adapter_examples')
Expand Down
43 changes: 42 additions & 1 deletion t3/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@
from arc.species.species import ARCSpecies, check_label
from arc.species.converter import check_xyz_dict

from t3.common import PROJECTS_BASE_PATH, VALID_CHARS, delete_root_rmg_log, get_species_by_label, time_lapse
from t3.common import (DATA_BASE_PATH,
PROJECTS_BASE_PATH,
VALID_CHARS,
delete_root_rmg_log,
get_species_by_label,
time_lapse)
from t3.logger import Logger
from t3.runners.rmg_runner import rmg_runner
from t3.schema import InputBase
Expand Down Expand Up @@ -177,6 +182,7 @@ def __init__(self,
self.project_directory = self.schema['project_directory']
self.t3 = self.schema['t3']
self.rmg = self.schema['rmg']
self.rmg['database'] = auto_complete_rmg_libraries(database=self.rmg['database'])
self.qm = self.schema['qm']
self.verbose = self.schema['verbose']

Expand Down Expand Up @@ -1538,3 +1544,38 @@ def get_species_with_qm_label(species: Species,
rmg_species=qm_species,
)
return qm_species


def auto_complete_rmg_libraries(database: dict) -> dict:
"""
Update the RMG libraries using auto-completion.
Args:
database (dict): The RMG libraries dictionary.
Returns:
dict: The updated RMG libraries dictionary.
"""
database['thermo_libraries'] = database['thermo_libraries'] or list()
database['kinetics_libraries'] = database['kinetics_libraries'] or list()
if database['chemistry_sets'] is not None:
libraries_dict = read_yaml_file(path=os.path.join(DATA_BASE_PATH, 'libraries.yml'))
low_credence = database['use_low_credence_libraries']
for chemistry_set in database['chemistry_sets']:
if chemistry_set not in libraries_dict:
raise ValueError(f"Chemistry set '{chemistry_set}' not found in the libraries.yml file.")
for key, libraries in zip(['thermo', 'kinetics'], [database['thermo_libraries'], database['kinetics_libraries']]):
low_credence_libraries = list()
if key in libraries_dict[chemistry_set]:
for entry in libraries_dict[chemistry_set][key]:
if isinstance(entry, str) and entry not in libraries:
libraries.append(entry)
elif isinstance(entry, dict):
if entry['credence'] != 'low' and entry['name'] not in libraries:
libraries.append(entry['name'])
if entry['credence'] == 'low' and low_credence and entry['name'] not in libraries:
low_credence_libraries.append(entry['name'])
libraries.extend(low_credence_libraries)
del database['chemistry_sets']
del database['use_low_credence_libraries']
return database
24 changes: 19 additions & 5 deletions t3/schema.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
"""
t3 schema module
used for input validation
Todo: add "live" validators for actually implemented adapters, need to access the respective factory register dicts
"""

import os
from enum import Enum
from typing import Dict, List, Optional, Tuple, Union

from pydantic import BaseModel, conint, confloat, constr, root_validator, validator

from t3.common import VALID_CHARS
from arc.common import read_yaml_file

from t3.common import DATA_BASE_PATH, VALID_CHARS
from t3.simulate.factory import _registered_simulate_adapters


Expand Down Expand Up @@ -174,8 +175,10 @@ class RMGDatabase(BaseModel):
"""
A class for validating input.RMG.database arguments
"""
thermo_libraries: List[str]
kinetics_libraries: List[str]
thermo_libraries: Optional[List[str]] = None
kinetics_libraries: Optional[List[str]] = None
chemistry_sets: Optional[List[str]] = None
use_low_credence_libraries: bool = False
transport_libraries: List[str] = ['OneDMinN2', 'PrimaryTransportLibrary', 'NOx2018', 'GRI-Mech']
seed_mechanisms: List[str] = list()
kinetics_depositories: Union[List[str], str] = 'default'
Expand All @@ -185,6 +188,17 @@ class RMGDatabase(BaseModel):
class Config:
extra = "forbid"

@validator('chemistry_sets')
def check_chemistry_sets(cls, value, values):
"""RMGDatabase.chemistry_sets validator"""
libraries_dict = read_yaml_file(path=os.path.join(DATA_BASE_PATH, 'libraries.yml'))
allowed_values = libraries_dict.keys()
if value and any(v not in allowed_values for v in value):
raise ValueError(f'The chemistry sets must be within of the following:\n{allowed_values}\nGot: {value}')
if value is None and (values['thermo_libraries'] is None or values['kinetics_libraries'] is None):
raise ValueError('The chemistry set must be specified if thermo or kinetics libraries are not specified.')
return value


class RadicalTypeEnum(str, Enum):
"""
Expand Down
13 changes: 12 additions & 1 deletion tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,18 @@ def run_minimal(project: Optional[str] = None,
iteration: Optional[int] = None,
set_paths: bool = False,
) -> T3:
"""A helper function for running the minimal example"""
"""
A helper function for running the minimal example.
Args:
project (str, optional): The project name.
project_directory (str, optional): The project directory.
iteration (int, optional): The iteration number.
set_paths (bool, optional): Whether to set the paths.
Returns:
T3: The T3 object.
"""
minimal_input = os.path.join(EXAMPLES_BASE_PATH, 'minimal', 'input.yml')
input_dict = read_yaml_file(path=minimal_input)
input_dict['verbose'] = 10
Expand Down
6 changes: 3 additions & 3 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from rmgpy.species import Species

import t3.common as common
from t3.common import DATA_BASE_PATH
from t3.common import TEST_DATA_BASE_PATH
from t3.schema import RMGSpecies
from tests.common import run_minimal

Expand All @@ -33,7 +33,7 @@ def test_dict_to_str():

def test_get_species_by_label():
"""Test getting species by label"""
t3 = run_minimal(project_directory=os.path.join(DATA_BASE_PATH, 'minimal_data'),
t3 = run_minimal(project_directory=os.path.join(TEST_DATA_BASE_PATH, 'minimal_data'),
iteration=1,
set_paths=True,
)
Expand Down Expand Up @@ -131,7 +131,7 @@ def test_get_interval():

def test_get_chem_to_rmg_rxn_index_map():
"""Test the get_chem_to_rmg_rxn_index_map() function"""
chemkin_path = os.path.join(DATA_BASE_PATH, 'chem_annotated_1.inp')
chemkin_path = os.path.join(TEST_DATA_BASE_PATH, 'chem_annotated_1.inp')
rxn_map = common.get_chem_to_rmg_rxn_index_map(chem_annotated_path=chemkin_path)
assert rxn_map == {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 5, 7: 6, 8: 7, 9: 8, 10: 9, 11: 9, 12: 10, 13: 11, 14: 12,
15: 13, 16: 14, 17: 15, 18: 16, 19: 17, 20: 18, 21: 19, 22: 20, 23: 21, 24: 22, 25: 23, 26: 24,
Expand Down
10 changes: 5 additions & 5 deletions tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from arc.common import read_yaml_file

from t3 import T3
from t3.common import DATA_BASE_PATH
from t3.common import TEST_DATA_BASE_PATH
from t3.runners.rmg_runner import backup_rmg_files
from t3.utils.dependencies import check_dependencies

Expand Down Expand Up @@ -58,7 +58,7 @@ def test_computing_thermo():
Tests computing thermo for two species and running RMG with the updated data
Need xtb installed
"""
functional_test_directory = os.path.join(DATA_BASE_PATH, 'functional_2_thermo')
functional_test_directory = os.path.join(TEST_DATA_BASE_PATH, 'functional_2_thermo')
#delete_selective_content_from_test_dirs(test_dir=functional_test_directory)
input_file = os.path.join(functional_test_directory, 'input.yml')
input_dict = read_yaml_file(path=input_file)
Expand Down Expand Up @@ -113,7 +113,7 @@ def test_rmg_files_backup_before_restart():
3.chem_edge_annotated
4.RMG log files
"""
backup_test_directory = os.path.join(DATA_BASE_PATH, 'backup_rmg_files_before_restart','iteration_1', 'RMG')
backup_test_directory = os.path.join(TEST_DATA_BASE_PATH, 'backup_rmg_files_before_restart','iteration_1', 'RMG')
backup_rmg_files(backup_test_directory)
# Find the backup directory (there should only be one per restart)
backup_directories = [d for d in os.listdir(backup_test_directory) if d.startswith('restart_backup')]
Expand Down Expand Up @@ -152,11 +152,11 @@ def delete_selective_content_from_test_dirs(test_dir: str):

def teardown_module():
"""teardown any state that was previously setup with a setup_module method."""
test_dirs_to_selectively_delete = [os.path.join(DATA_BASE_PATH, 'functional_2_thermo'),
test_dirs_to_selectively_delete = [os.path.join(TEST_DATA_BASE_PATH, 'functional_2_thermo'),
]
for test_dir in test_dirs_to_selectively_delete:
delete_selective_content_from_test_dirs(test_dir)
test_dirs = [os.path.join(DATA_BASE_PATH, 'T3_functional_test_1'),
test_dirs = [os.path.join(TEST_DATA_BASE_PATH, 'T3_functional_test_1'),
]
for test_dir in test_dirs:
shutil.rmtree(test_dir, ignore_errors=True)
Loading

0 comments on commit 2d7c1ca

Please sign in to comment.