Skip to content

Commit

Permalink
Merge branch 'main' into fix-doc-typo
Browse files Browse the repository at this point in the history
  • Loading branch information
jonwzheng authored Aug 6, 2024
2 parents ade7315 + a4cbbf8 commit 9efd31c
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 46 deletions.
37 changes: 19 additions & 18 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ env:

jobs:
build-osx:
runs-on: macos-latest
runs-on: macos-13
# skip scheduled runs from forks
if: ${{ !( github.repository != 'ReactionMechanismGenerator/RMG-Py' && github.event_name == 'schedule' ) }}
defaults:
Expand All @@ -63,7 +63,7 @@ jobs:

# configures the mamba environment manager and builds the environment
- name: Setup Mambaforge Python 3.7
uses: conda-incubator/setup-miniconda@v2
uses: conda-incubator/setup-miniconda@v3
with:
environment-file: environment.yml
miniforge-variant: Mambaforge
Expand Down Expand Up @@ -113,7 +113,7 @@ jobs:

# configures the mamba environment manager and builds the environment
- name: Setup Mambaforge Python 3.7
uses: conda-incubator/setup-miniconda@v2
uses: conda-incubator/setup-miniconda@v3
with:
environment-file: environment.yml
miniforge-variant: Mambaforge
Expand Down Expand Up @@ -167,7 +167,7 @@ jobs:
id: regression-execution
timeout-minutes: 60
run: |
for regr_test in aromatics liquid_oxidation nitrogen oxidation sulfur superminimal RMS_constantVIdealGasReactor_superminimal RMS_CSTR_liquid_oxidation RMS_liquidSurface_ch4o2cat fragment RMS_constantVIdealGasReactor_fragment minimal_surface;
for regr_test in aromatics liquid_oxidation nitrogen oxidation sulfur superminimal RMS_constantVIdealGasReactor_superminimal RMS_CSTR_liquid_oxidation RMS_liquidSurface_ch4o2cat fragment RMS_constantVIdealGasReactor_fragment;
do
if python-jl rmg.py test/regression/"$regr_test"/input.py; then
echo "$regr_test" "Executed Successfully"
Expand All @@ -185,7 +185,7 @@ jobs:
# Upload Regression Results as Failed if above step failed
- name: Upload Failed Results
if: ${{ failure() && steps.regression-execution.conclusion == 'failure' }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: failed_regression_results
path: |
Expand All @@ -195,7 +195,7 @@ jobs:
- name: Upload Results as Reference
# upload the results for scheduled CI (on main) and pushes to main
if: ${{ env.REFERENCE_JOB == 'true' }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: stable_regression_results
path: |
Expand All @@ -204,7 +204,7 @@ jobs:
# Upload Regression Results as Dynamic if Push to non-main Branch
- name: Upload Results as Dynamic
if: ${{ env.REFERENCE_JOB == 'false' }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: dynamic_regression_results
path: |
Expand All @@ -215,23 +215,24 @@ jobs:
run: mkdir stable_regression_results

# Retrieve Stable Results for reference
# Will need to use this -> https://github.com/dawidd6/action-download-artifact
- name : Find ID of Reference Results
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
run_id=$(gh run list -R ReactionMechanismGenerator/RMG-Py --workflow="Continuous Integration" --branch main --limit 1 --json databaseId --jq '.[0].databaseId')
echo "CI_RUN_ID=$run_id" >> $GITHUB_ENV
- name: Retrieve Stable Regression Results
if: ${{ env.REFERENCE_JOB == 'false' }}
uses: dsnopek/action-download-artifact@91dda23aa09c68860977dd0ed11d93c0ed3795e7 # see https://github.com/ReactionMechanismGenerator/RMG-Py/pull/2459#issuecomment-1582850815
uses: actions/download-artifact@v4
with:
# this will search for the last successful execution of CI on main and download
# the stable regression results
workflow: CI.yml
workflow_conclusion: success
repo: ReactionMechanismGenerator/RMG-Py
branch: main
run-id: ${{ env.CI_RUN_ID }}
repository: ReactionMechanismGenerator/RMG-Py
github-token: ${{ secrets.GITHUB_TOKEN }}
name: stable_regression_results
path: stable_regression_results
search_artifacts: true # retrieves the last run result, either scheduled daily or on push to main
ensure_latest: true # ensures that the latest run is retrieved
# should result in a set of folders inside stable_regression_results
# each of which has the stable result for that example/test

# Regression Testing - Actual Comparisons
- name: Regression Tests - Compare to Baseline
Expand All @@ -242,7 +243,7 @@ jobs:
run: |
exec 2> >(tee -a regression.stderr >&2) 1> >(tee -a regression.stdout)
mkdir -p "test/regression-diff"
for regr_test in aromatics liquid_oxidation nitrogen oxidation sulfur superminimal RMS_constantVIdealGasReactor_superminimal RMS_CSTR_liquid_oxidation fragment RMS_constantVIdealGasReactor_fragment minimal_surface;
for regr_test in aromatics liquid_oxidation nitrogen oxidation sulfur superminimal RMS_constantVIdealGasReactor_superminimal RMS_CSTR_liquid_oxidation fragment RMS_constantVIdealGasReactor_fragment;
do
echo ""
echo "### Regression test $regr_test:"
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#
################################################################################

CC=gcc
CXX=g++

.PHONY : all minimal main solver check pycheck arkane clean install decython documentation test q2dtor

all: pycheck main solver check
Expand Down
5 changes: 3 additions & 2 deletions arkane/ess/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ class ESSAdapter(ABC):
An abstract ESS Adapter class
"""

def __init__(self, path, check_for_errors=True):
def __init__(self, path, check_for_errors=True, scratch_directory=None):
self.path = path
if check_for_errors:
self.check_for_errors()
self.scratch_directory = scratch_directory if scratch_directory is not None else os.path.join(os.path.abspath('.'), str('scratch'))

@abstractmethod
def check_for_errors(self):
Expand Down Expand Up @@ -174,7 +175,7 @@ def get_symmetry_properties(self):
coordinates, atom_numbers, _ = self.load_geometry()
unique_id = '0' # Just some name that the SYMMETRY code gives to one of its jobs
# Scratch directory that the SYMMETRY code writes its files in:
scr_dir = os.path.join(os.path.abspath('.'), str('scratch'))
scr_dir = self.scratch_directory
if not os.path.exists(scr_dir):
os.makedirs(scr_dir)
try:
Expand Down
3 changes: 2 additions & 1 deletion arkane/ess/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def register_ess_adapter(ess: str,

def ess_factory(fullpath: str,
check_for_errors: bool = True,
scratch_directory: str = None,
) -> Type[ESSAdapter]:
"""
A factory generating the ESS adapter corresponding to ``ess_adapter``.
Expand Down Expand Up @@ -106,4 +107,4 @@ def ess_factory(fullpath: str,
raise InputError(f'The file at {fullpath} could not be identified as a '
f'Gaussian, Molpro, Orca, Psi4, QChem, or TeraChem log file.')

return _registered_ess_adapters[ess_name](path=fullpath, check_for_errors=check_for_errors)
return _registered_ess_adapters[ess_name](path=fullpath, check_for_errors=check_for_errors, scratch_directory=scratch_directory)
6 changes: 2 additions & 4 deletions arkane/ess/gaussian.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import logging
import math
import os.path

import re
import numpy as np

import rmgpy.constants as constants
Expand Down Expand Up @@ -309,9 +309,8 @@ def load_energy(self, zpe_scale_factor=1.):
with open(self.path, 'r') as f:
line = f.readline()
while line != '':

if 'SCF Done:' in line:
e_elect = float(line.split()[4]) * constants.E_h * constants.Na
e_elect = float(re.findall(r"SCF Done: E\(.+\) \=\s+[^\s]+", line)[0].split()[-1]) * constants.E_h * constants.Na
elect_energy_source = 'SCF'
elif ' E2(' in line and ' E(' in line:
e_elect = float(line.split()[-1].replace('D', 'E')) * constants.E_h * constants.Na
Expand Down Expand Up @@ -351,7 +350,6 @@ def load_energy(self, zpe_scale_factor=1.):
# G4MP2 calculation without opt and freq calculation
# Keyword in Gaussian G4MP2(SP), No zero-point or thermal energies are included.
e_elect = float(line.split()[2]) * constants.E_h * constants.Na

# Read the ZPE from the "E(ZPE)=" line, as this is the scaled version.
# Gaussian defines the following as
# E (0 K) = Elec + E(ZPE),
Expand Down
21 changes: 19 additions & 2 deletions documentation/source/users/rmg/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ by Benson's method.

For example, if you wish to use the GRI-Mech 3.0 mechanism [GRIMech3.0]_ as a ThermoLibrary in your model, the syntax will be::

thermoLibraries = ['primaryThermoLibrary','GRI-Mech3.0']
thermoLibraries = ['primaryThermoLibrary', 'GRI-Mech3.0']

.. [GRIMech3.0] Gregory P. Smith, David M. Golden, Michael Frenklach, Nigel W. Moriarty, Boris Eiteneer, Mikhail Goldenberg, C. Thomas Bowman, Ronald K. Hanson, Soonho Song, William C. Gardiner, Jr., Vitali V. Lissianski, and Zhiwei Qin http://combustion.berkeley.edu/gri-mech/
Expand Down Expand Up @@ -78,7 +78,7 @@ In the following example, the user has created
a reaction library with a few additional reactions specific to n-butane, and these reactions
are to be used in addition to the Glarborg C3 library::

reactionLibraries = [('Glarborg/C3',False)],
reactionLibraries = [('Glarborg/C3', False)],

The keyword False/True permits user to append all unused reactions (= kept in the edge) from this library to the chemkin file.
True means those reactions will be appended. Using just the string inputs would lead to
Expand All @@ -104,6 +104,23 @@ given in each mechanism, the different mechanisms can have different units.
Library.


.. _externallib:

External Libraries
------------------
Users may direct RMG to use thermo and/or kinetic libraries which are not included in the RMG database,
e.g., a library a user created that was intentionally saved to a path different than the conventional
RMG-database location. In such cases, the user can specify the full path to the library in the input file::

thermoLibraries = ['path/to/your/thermo/library/file.py']

or::

reactionLibraries = [(path/to/your/kinetic/library/folder/']

Combinations in any order of RMG's legacy libraries and users' external libraries are allowed,
and the order in which the libraries are specified is the order in which they are loaded and given priority.

.. _seedmechanism:

Seed Mechanisms
Expand Down
10 changes: 5 additions & 5 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# made dependency list more explicit (@JacksonBurns).
# - October 16, 2023 Switched RDKit and descripatastorus to conda-forge,
# moved diffeqpy to pip and (temporarily) removed chemprop
#
# - August 4, 2024 Restricted pyrms to <2
name: rmg_env
channels:
- defaults
Expand Down Expand Up @@ -81,14 +81,14 @@ dependencies:
- conda-forge::gprof2dot
- conda-forge::numdifftools
- conda-forge::quantities
- conda-forge::muq
- conda-forge::lpsolve55
- conda-forge::ringdecomposerlib-python

# packages we maintain
- rmg::lpsolve55
- rmg::muq2
- rmg::pydas >=1.0.3
- rmg::pydqed >=1.0.3
- rmg::pyrdl
- rmg::pyrms
- rmg::pyrms <2
- rmg::symmetry

# packages we would like to stop maintaining (and why)
Expand Down
6 changes: 4 additions & 2 deletions rmgpy/data/kinetics/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def __init__(self):
self.recommended_families = {}
self.families = {}
self.libraries = {}
self.external_library_labels = {}
self.library_order = [] # a list of tuples in the format ('library_label', LibraryType),
# where LibraryType is set to either 'Reaction Library' or 'Seed'.
self.local_context = {
Expand Down Expand Up @@ -227,17 +228,18 @@ def load_libraries(self, path, libraries=None):
The `path` points to the folder of kinetics libraries in the database,
and the libraries should be in files like :file:`<path>/<library>.py`.
"""

self.external_library_labels = dict()
if libraries is not None:
for library_name in libraries:
library_file = os.path.join(path, library_name, 'reactions.py')
if os.path.exists(library_name):
library_file = os.path.join(library_name, 'reactions.py')
short_library_name = os.path.split(library_name)[-1]
short_library_name = os.path.basename(library_name.rstrip(os.path.sep))
logging.info(f'Loading kinetics library {short_library_name} from {library_name}...')
library = KineticsLibrary(label=short_library_name)
library.load(library_file, self.local_context, self.global_context)
self.libraries[library.label] = library
self.external_library_labels[library_name] = library.label
elif os.path.exists(library_file):
logging.info(f'Loading kinetics library {library_name} from {library_file}...')
library = KineticsLibrary(label=library_name)
Expand Down
30 changes: 25 additions & 5 deletions rmgpy/molecule/draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,7 @@ def __init__(self, options=None):
self.options = MoleculeDrawer().options.copy()
self.options.update({
'arrowLength': 36,
'drawReversibleArrow': True
})
if options:
self.options.update(options)
Expand Down Expand Up @@ -1744,11 +1745,30 @@ def draw(self, reaction, file_format, path=None):
rxn_cr.save()
rxn_cr.set_source_rgba(0.0, 0.0, 0.0, 1.0)
rxn_cr.set_line_width(1.0)
rxn_cr.move_to(rxn_x + 8, rxn_top + 0.5 * rxn_height)
rxn_cr.line_to(rxn_x + arrow_width - 8, rxn_top + 0.5 * rxn_height)
rxn_cr.move_to(rxn_x + arrow_width - 14, rxn_top + 0.5 * rxn_height - 3.0)
rxn_cr.line_to(rxn_x + arrow_width - 8, rxn_top + 0.5 * rxn_height)
rxn_cr.line_to(rxn_x + arrow_width - 14, rxn_top + 0.5 * rxn_height + 3.0)
if self.options['drawReversibleArrow'] and reaction.reversible: # draw double harpoons
TOP_HARPOON_Y = rxn_top + (0.5 * rxn_height - 1.75)
BOTTOM_HARPOON_Y = rxn_top + (0.5 * rxn_height + 1.75)

# Draw top harpoon
rxn_cr.move_to(rxn_x + 8, TOP_HARPOON_Y)
rxn_cr.line_to(rxn_x + arrow_width - 8, TOP_HARPOON_Y)
rxn_cr.move_to(rxn_x + arrow_width - 14, TOP_HARPOON_Y - 3.0)
rxn_cr.line_to(rxn_x + arrow_width - 8, TOP_HARPOON_Y)

# Draw bottom harpoon
rxn_cr.move_to(rxn_x + arrow_width - 8, BOTTOM_HARPOON_Y)
rxn_cr.line_to(rxn_x + 8, BOTTOM_HARPOON_Y)
rxn_cr.move_to(rxn_x + 14, BOTTOM_HARPOON_Y + 3.0)
rxn_cr.line_to(rxn_x + 8, BOTTOM_HARPOON_Y)


else: # draw forward arrow
rxn_cr.move_to(rxn_x + 8, rxn_top + 0.5 * rxn_height)
rxn_cr.line_to(rxn_x + arrow_width - 8, rxn_top + 0.5 * rxn_height)
rxn_cr.move_to(rxn_x + arrow_width - 14, rxn_top + 0.5 * rxn_height - 3.0)
rxn_cr.line_to(rxn_x + arrow_width - 8, rxn_top + 0.5 * rxn_height)
rxn_cr.line_to(rxn_x + arrow_width - 14, rxn_top + 0.5 * rxn_height + 3.0)

rxn_cr.stroke()
rxn_cr.restore()
rxn_x += arrow_width
Expand Down
8 changes: 4 additions & 4 deletions rmgpy/reaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -1030,15 +1030,15 @@ def generate_reverse_rate_coefficient(self, network_kinetics=False, Tmin=None, T
return self.reverse_arrhenius_rate(kf, kunits)

elif isinstance(kf, Chebyshev):
Tlist = 1.0 / np.linspace(1.0 / kf.Tmax.value, 1.0 / kf.Tmin.value, 50)
Plist = np.linspace(kf.Pmin.value, kf.Pmax.value, 20)
Tlist = 1.0 / np.linspace(1.0 / kf.Tmax.value_si, 1.0 / kf.Tmin.value_si, 50)
Plist = np.linspace(kf.Pmin.value_si, kf.Pmax.value_si, 20)
K = np.zeros((len(Tlist), len(Plist)), float)
for Tindex, T in enumerate(Tlist):
for Pindex, P in enumerate(Plist):
K[Tindex, Pindex] = kf.get_rate_coefficient(T, P) / self.get_equilibrium_constant(T)
kr = Chebyshev()
kr.fit_to_data(Tlist, Plist, K, kunits, kf.degreeT, kf.degreeP, kf.Tmin.value, kf.Tmax.value, kf.Pmin.value,
kf.Pmax.value)
kr.fit_to_data(Tlist, Plist, K, kunits, kf.degreeT, kf.degreeP, kf.Tmin.value, kf.Tmax.value,
kf.Pmin.value_si, kf.Pmax.value_si)
return kr

elif isinstance(kf, PDepArrhenius):
Expand Down
7 changes: 6 additions & 1 deletion rmgpy/rmg/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1718,7 +1718,12 @@ def add_reaction_library_to_edge(self, reaction_library):
num_old_edge_reactions = len(self.edge.reactions)

logging.info("Adding reaction library {0} to model edge...".format(reaction_library))
reaction_library = database.kinetics.libraries[reaction_library]
if reaction_library in database.kinetics.libraries:
reaction_library = database.kinetics.libraries[reaction_library]
elif reaction_library in database.kinetics.external_library_labels:
reaction_library = database.kinetics.libraries[database.kinetics.external_library_labels[reaction_library]]
else:
raise ValueError(f'Library {reaction_library} not found.')

rxns = reaction_library.get_library_reactions()
for rxn in rxns:
Expand Down
4 changes: 2 additions & 2 deletions test/rmgpy/data/transportTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ def test_joback(self):
[
"acetone",
"CC(=O)C",
Length(5.36421, "angstroms"),
Length(5.32979, "angstroms"),
Energy(3.20446, "kJ/mol"),
"Epsilon & sigma estimated with Tc=500.53 K, Pc=47.11 bar (from Joback method)",
"Epsilon & sigma estimated with Tc=500.53 K, Pc=48.02 bar (from Joback method)",
],
[
"cyclopenta-1,2-diene",
Expand Down

0 comments on commit 9efd31c

Please sign in to comment.