Skip to content

Commit d0075df

Browse files
authored
Merge pull request #2981 from ReactionMechanismGenerator/main
RMG-Py v4.0.0 `stable`
2 parents 7c363ca + 643259b commit d0075df

373 files changed

Lines changed: 37211 additions & 77811 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.conda/conda_build_config.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Restrict conda-build's variant matrix so the solver does not enumerate
2+
# python/numpy combinations from internal_defaults. The CI workflow's
3+
# CONDA_PY env var narrows to one of these python versions per matrix cell.
4+
#
5+
# Without this file, conda-build considers every (python, numpy) pair from
6+
# its internal defaults during the "Getting pinned dependencies" phase,
7+
# which substantially enlarges the search space the libmamba solver has
8+
# to traverse.
9+
python:
10+
- 3.9
11+
- 3.10
12+
- 3.11
13+
numpy:
14+
- 1.26

.conda/meta.yaml

Lines changed: 27 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -4,173 +4,76 @@
44
# RMG-Py into binaries which can then be uploaded for access via the conda package manager
55
# to use this file, you can follow the procedure shown in .github/workflows/conda_build.yml
66
#
7+
# Variant axes (python, numpy) are pinned in .conda/conda_build_config.yaml so that
8+
# conda-build does not enumerate every combination from its internal defaults.
9+
#
710
package:
811
name: rmg
9-
version: 3.3.0
12+
version: 4.0.0
1013

1114
source:
1215
path: ../
1316

1417
build:
1518
number: 0
1619
script: |
17-
python utilities.py check-pydas # write the rmgpy/solver/settings.pxi file
18-
python setup.py install --single-version-externally-managed --record=record.txt
20+
{{ PYTHON }} utilities.py check-pydas # write the rmgpy/solver/settings.pxi file
21+
{{ PYTHON }} setup.py install --single-version-externally-managed --record=record.txt
1922
2023
requirements:
2124
build:
2225
- {{ compiler('c') }}
23-
host:
24-
- conda-forge::cairo
25-
- conda-forge::cairocffi
26-
- conda-forge::ffmpeg >=7
27-
- conda-forge::xlrd
28-
- conda-forge::xlwt
29-
- conda-forge::h5py
30-
- conda-forge::graphviz >=12
31-
- conda-forge::markupsafe
32-
- conda-forge::psutil
33-
- conda-forge::ncurses
34-
- conda-forge::suitesparse
35-
- conda-forge::graphviz
36-
- conda-forge::pyopenssl >20
37-
- conda-forge::coolprop
38-
- conda-forge::cantera =2.6
39-
- conda-forge::mopac
40-
- conda-forge::cclib >=1.6.3,<1.9
41-
- conda-forge::openbabel >=3
42-
- conda-forge::rdkit >=2022.09.1
43-
- conda-forge::python >=3.9
44-
- conda-forge::setuptools <80
45-
- conda-forge::coverage
46-
- conda-forge::cython >=0.25.2,<3.1
47-
- conda-forge::scikit-learn
48-
- conda-forge::scipy >=1.9
49-
- conda-forge::numpy >=1.10.0,<2
50-
- conda-forge::pydot
51-
- conda-forge::jinja2
52-
- conda-forge::jupyter
53-
- conda-forge::pymongo
54-
- conda-forge::pyparsing
55-
- conda-forge::pyyaml
56-
- conda-forge::networkx
57-
- conda-forge::pytest
58-
- conda-forge::pytest-cov
59-
- conda-forge::pytest-check
60-
- conda-forge::pyutilib
61-
- conda-forge::matplotlib >=1.5
62-
- conda-forge::mpmath
63-
- conda-forge::pandas
64-
- conda-forge::gprof2dot
65-
- conda-forge::numdifftools
66-
- conda-forge::quantities !=0.16.0,!=0.16.1
67-
- conda-forge::ringdecomposerlib-python
68-
- rmg::pydas >=1.0.3
69-
- rmg::pydqed >=1.0.3
70-
- rmg::symmetry
71-
- rmg::rmgdatabase =3.3.0
72-
- blas=*=openblas
73-
run:
26+
host: &runtime_requirements
7427
- conda-forge::cairo
7528
- conda-forge::cairocffi
7629
- conda-forge::ffmpeg >=7
7730
- conda-forge::xlrd
7831
- conda-forge::xlwt
79-
- conda-forge::h5py
32+
- conda-forge::h5py >=3.10
8033
- conda-forge::graphviz >=12
8134
- conda-forge::markupsafe
8235
- conda-forge::psutil
8336
- conda-forge::ncurses
8437
- conda-forge::suitesparse
85-
- conda-forge::graphviz
86-
- conda-forge::pyopenssl >20
38+
- conda-forge::pyopenssl >24
8739
- conda-forge::coolprop
88-
- conda-forge::cantera =2.6
40+
- conda-forge::cantera >=3.0
8941
- conda-forge::mopac
9042
- conda-forge::cclib >=1.6.3,<1.9
9143
- conda-forge::openbabel >=3
92-
- conda-forge::rdkit >=2022.09.1
93-
- conda-forge::python >=3.9
94-
- conda-forge::setuptools <80
95-
- conda-forge::coverage
96-
- conda-forge::cython >=0.25.2,<3.1
97-
- conda-forge::scikit-learn
98-
- conda-forge::scipy >=1.9
99-
- conda-forge::numpy >=1.10.0,<2
44+
- conda-forge::rdkit >=2024
45+
# python intentionally left loose so the CI matrix (via CONDA_PY)
46+
# can pin it without a contradictory-deps error. The real variant pin
47+
# lives in .conda/conda_build_config.yaml.
48+
- conda-forge::python >=3.9,<3.12
49+
- conda-forge::setuptools >=70,<80
50+
- conda-forge::cython >=3.0,<3.1
51+
- conda-forge::scikit-learn >=1.3
52+
- conda-forge::scipy >=1.13
53+
- conda-forge::numpy >=1.24,<2
10054
- conda-forge::pydot
10155
- conda-forge::jinja2
102-
- conda-forge::jupyter
10356
- conda-forge::pymongo
10457
- conda-forge::pyparsing
10558
- conda-forge::pyyaml
10659
- conda-forge::networkx
107-
- conda-forge::pytest
108-
- conda-forge::pytest-cov
109-
- conda-forge::pytest-check
11060
- conda-forge::pyutilib
111-
- conda-forge::matplotlib >=1.5
61+
- conda-forge::matplotlib >=3.5
11262
- conda-forge::mpmath
113-
- conda-forge::pandas
63+
- conda-forge::pandas >=2
11464
- conda-forge::gprof2dot
11565
- conda-forge::numdifftools
11666
- conda-forge::quantities !=0.16.0,!=0.16.1
117-
- conda-forge::ringdecomposerlib-python
67+
- rmg::pysidt-rmg >=1.2
11868
- rmg::pydas >=1.0.3
11969
- rmg::pydqed >=1.0.3
12070
- rmg::symmetry
121-
- rmg::rmgdatabase =3.3.0
71+
- rmg::rmgdatabase =4.0.0
12272
- blas=*=openblas
73+
run: *runtime_requirements
12374
test:
124-
requires:
125-
- conda-forge::cairo
126-
- conda-forge::cairocffi
127-
- conda-forge::ffmpeg >=7
128-
- conda-forge::xlrd
129-
- conda-forge::xlwt
130-
- conda-forge::h5py
131-
- conda-forge::graphviz >=12
132-
- conda-forge::markupsafe
133-
- conda-forge::psutil
134-
- conda-forge::ncurses
135-
- conda-forge::suitesparse
136-
- conda-forge::graphviz
137-
- conda-forge::pyopenssl >20
138-
- conda-forge::coolprop
139-
- conda-forge::cantera =2.6
140-
- conda-forge::mopac
141-
- conda-forge::cclib >=1.6.3,<1.9
142-
- conda-forge::openbabel >=3
143-
- conda-forge::rdkit >=2022.09.1
144-
- conda-forge::python >=3.9
145-
- conda-forge::setuptools <80
146-
- conda-forge::coverage
147-
- conda-forge::cython >=0.25.2,<3.1
148-
- conda-forge::scikit-learn
149-
- conda-forge::scipy >=1.9
150-
- conda-forge::numpy >=1.10.0,<2
151-
- conda-forge::pydot
152-
- conda-forge::jinja2
153-
- conda-forge::jupyter
154-
- conda-forge::pymongo
155-
- conda-forge::pyparsing
156-
- conda-forge::pyyaml
157-
- conda-forge::networkx
158-
- conda-forge::pytest
159-
- conda-forge::pytest-cov
160-
- conda-forge::pytest-check
161-
- conda-forge::pyutilib
162-
- conda-forge::matplotlib >=1.5
163-
- conda-forge::mpmath
164-
- conda-forge::pandas
165-
- conda-forge::gprof2dot
166-
- conda-forge::numdifftools
167-
- conda-forge::quantities !=0.16.0,!=0.16.1
168-
- conda-forge::ringdecomposerlib-python
169-
- rmg::pydas >=1.0.3
170-
- rmg::pydqed >=1.0.3
171-
- rmg::symmetry
172-
- rmg::rmgdatabase =3.3.0
173-
- blas=*=openblas
75+
# Keep this minimal: test commands below run import checks plus two example
76+
# command-line runs, and do not invoke the pytest suite.
17477
source_files:
17578
- 'examples/rmg/superminimal'
17679
- 'examples/arkane/networks/n-butanol_msc'

.github/copilot-instructions.md

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# RMG-Py Copilot Instructions
2+
3+
## Project Overview
4+
RMG-Py is the Reaction Mechanism Generator - an automatic chemical kinetics mechanism generator. It consists of two main components:
5+
- **RMG** (`rmgpy/`): Core mechanism generation engine
6+
- **Arkane** (`arkane/`): Statistical mechanics and transition state theory calculations
7+
8+
## Architecture
9+
10+
### Core Packages
11+
- `rmgpy/molecule/` - Molecular graph representation (`Molecule`, `Atom`, `Bond`, `Group`)
12+
- `rmgpy/thermo/` - Thermodynamic models (NASA, Wilhoit, ThermoData)
13+
- `rmgpy/kinetics/` - Rate coefficient models (Arrhenius, Chebyshev, pressure-dependent)
14+
- `rmgpy/solver/` - ODE solvers for reactor simulations
15+
- `rmgpy/rmg/` - Main RMG algorithm (`main.py`, `model.py`, `react.py`)
16+
- `rmgpy/data/` - Database interfaces for thermo, kinetics, transport
17+
18+
### Key Base Classes
19+
- `RMGObject` (in `rmgpy/rmgobject.pyx`) - Base class providing `as_dict()`/`make_object()` for YAML serialization
20+
- `Graph`/`Vertex`/`Edge` (in `rmgpy/molecule/graph.pyx`) - Graph isomorphism via VF2 algorithm
21+
- `Species` and `Reaction` are central objects connecting molecules to thermodynamics and kinetics
22+
23+
### Cython Architecture
24+
Performance-critical code uses Cython (`.pyx` files) with declaration files (`.pxd`):
25+
- Some `.py` files are also cythonized — they have a `.pxd` sibling and are listed in `setup.py` `ext_modules` (e.g. `rmgpy/species.py`, `rmgpy/reaction.py`, `rmgpy/quantity.py`, `rmgpy/constants.py`, and most of `rmgpy/molecule/`). The compiled `.so` is what gets imported, so edits won't take effect until rebuilt.
26+
- Always pair `.pyx` (or cythonized `.py`) with `.pxd` for public cdef classes/methods
27+
- Use `cpdef` for methods callable from both Python and Cython
28+
- Use `cimport` for Cython-level imports (e.g., `cimport rmgpy.constants as constants`)
29+
- Register new Cython modules in `setup.py` `ext_modules` list
30+
- Remember to re-compile (`make build`) after modifying any `.pyx`, `.pxd`, or cythonized `.py` file, or if there seem to be weird bugs in them.
31+
32+
## Development Commands
33+
```bash
34+
make install # First-time pip editable install + Cython build. Writes a .installed sentinel; subsequent `make install` is a no-op until `make clean`.
35+
make build # Incremental in-place Cython rebuild (`setup.py build_ext --inplace`). Fast — use this after editing .pyx/.pxd/cythonized .py.
36+
make # Default target: dep check, install if needed (via sentinel), then `make build`. Safe go-to.
37+
make test # Run unit tests (excludes functional/database tests)
38+
make test-functional # Run functional tests
39+
make test-database # Run database tests
40+
make test-all # Run all tests
41+
make clean # Remove .so/.pyc/.c build artifacts, the build/ dir, the .installed sentinel, and pip-uninstall the package.
42+
make decython # Remove most .so files for "pure Python" debugging (keeps _statmech.so, quantity.so, and rmgpy/solver/*.so). Pure python mode is not reliably tested and might not work.
43+
make documentation # Build Sphinx docs
44+
```
45+
46+
## Testing Conventions
47+
- Tests live in `test/` mirroring `rmgpy/` and `arkane/` structure
48+
- Test files: `*Test.py` (e.g., `speciesTest.py`, `reactionTest.py`)
49+
- Test classes: `class TestClassName:` or `class ClassNameTest:`
50+
- Use `pytest` with fixtures (`@pytest.fixture(autouse=True)` for setup)
51+
- Markers: `@pytest.mark.functional`, `@pytest.mark.database`
52+
- Run specific tests: `pytest -k "test_name_pattern"`
53+
54+
## Code Patterns
55+
56+
### Molecular Representations
57+
```python
58+
from rmgpy.molecule import Molecule
59+
mol = Molecule().from_smiles("CC") # From SMILES
60+
mol = Molecule().from_adjacency_list("""...""") # From adjacency list
61+
mol.is_isomorphic(other_mol) # Graph isomorphism check
62+
```
63+
64+
### Species and Reactions
65+
```python
66+
from rmgpy.species import Species
67+
species = Species(label='ethane', molecule=[Molecule().from_smiles("CC")])
68+
species.generate_resonance_structures()
69+
```
70+
71+
```python
72+
from rmgpy.reaction import Reaction
73+
from rmgpy.kinetics import Arrhenius
74+
75+
# Reaction with Arrhenius kinetics
76+
rxn = Reaction(
77+
reactants=[Species(label='CH3', molecule=[Molecule(smiles='[CH3]')]),
78+
Species(label='O2', molecule=[Molecule(smiles='[O][O]')])],
79+
products=[Species(label='CH3OO', molecule=[Molecule(smiles='CO[O]')])],
80+
kinetics=Arrhenius(A=(2.65e12, 'cm^3/(mol*s)'), n=0.0, Ea=(0.0, 'kJ/mol'), T0=(1, 'K')),
81+
)
82+
83+
# Reaction without kinetics (e.g. for isomorphism checks)
84+
rxn2 = Reaction(
85+
reactants=[Species().from_smiles('[O]'), Species().from_smiles('O=S=O')],
86+
products=[Species().from_smiles('O=S(=O)=O')],
87+
)
88+
```
89+
90+
91+
## Input Files
92+
- RMG inputs: Python scripts defining `database()`, `species()`, `simpleReactor()`, etc.
93+
- See `examples/rmg/minimal/input.py` for structure and `examples/rmg/commented/input.py` for a file with detailed comments
94+
- Arkane inputs: Python scripts with `species()`, `transitionState()`, `reaction()` blocks
95+
- See `examples/arkane/` for examples
96+
97+
## RMG-database Integration
98+
The **RMG-database** is a separate repository containing all thermodynamic, kinetics, and transport data. It's typically cloned alongside RMG-Py in a sibling folder named `RMG-database`.
99+
100+
### Database Structure (in RMG-database `input/` directory, eg. `RMG-database/input/thermo/`)
101+
- `thermo/` - Thermodynamic libraries and group additivity data
102+
- `kinetics/families/` - Reaction family templates with rate rules (e.g., `H_Abstraction`, `R_Addition_MultipleBond`)
103+
- `kinetics/libraries/` - Curated rate coefficient libraries
104+
- `solvation/` - Solvent and solute parameters
105+
- `transport/` - Transport properties
106+
107+
### How RMG-Py Loads the Database
108+
The `RMGDatabase` class (`rmgpy/data/rmg.py`) is the central interface:
109+
```python
110+
from rmgpy.data.rmg import RMGDatabase
111+
database = RMGDatabase()
112+
database.load(
113+
path='/path/to/RMG-database/input',
114+
thermo_libraries=['primaryThermoLibrary'],
115+
kinetics_families='default',
116+
reaction_libraries=[],
117+
)
118+
```
119+
120+
### Key Database Classes
121+
- `ThermoDatabase` (`rmgpy/data/thermo.py`) - Estimates thermo via group additivity or libraries
122+
- `KineticsDatabase` (`rmgpy/data/kinetics/database.py`) - Manages reaction families and libraries
123+
- `KineticsFamily` (`rmgpy/data/kinetics/family.py`) - Template-based reaction generation using `Group` pattern matching
124+
- `Entry` (`rmgpy/data/base.py`) - Base class for database entries with metadata
125+
126+
### Data Flow for Species Thermodynamics
127+
1. `Species.get_thermo_data()``rmgpy.thermo.thermoengine.submit(species)`
128+
2. `thermoengine.submit()` generates resonance structures, then dispatches to `ThermoDatabase.get_thermo_data(species)`
129+
3. `ThermoDatabase` first checks thermo libraries for an exact match (via graph isomorphism)
130+
4. If no library match is found, `ThermoDatabase` falls back to group additivity estimation using functional group contributions
131+
5. The resolved result is returned as a `ThermoData`, `NASA`, or `Wilhoit` object
132+
133+
134+
### Data Flow for Reaction Kinetics
135+
1. `KineticsFamily.generate_reactions(reactants)` - Matches reactant molecules to family templates
136+
2. Creates `TemplateReaction` objects with labeled atoms from template matching
137+
3. `KineticsFamily.get_kinetics()` - Estimates rate using rate rules or training reactions
138+
4. Returns `Arrhenius` or pressure-dependent kinetics model
139+
140+
## External Dependencies
141+
- **RMG-database**: In CI, `RMG_DATABASE_BRANCH` controls which RMG-database branch is cloned. Locally, the database location is set via `settings['database.directory']` (default `../RMG-database/input`) or `database.directory` in an `rmgrc` file; you may also pass an explicit path to `database.load()`.
142+
- **Julia/RMS**: Optional (recommended) reactor simulation backend (install via `./install_rms.sh`)
143+
- Environment managed via `environment.yml` (conda/mamba)
144+
145+
## Documentation
146+
Documentation lives in `documentation/source/` and is built with Sphinx (`make documentation`).
147+
148+
### User Documentation (`documentation/source/users/`)
149+
- `users/rmg/` - RMG user guide (how to run, configure, interpret output)
150+
- `users/arkane/` - Arkane user guide
151+
- **Critical file**: `users/rmg/input.rst` - Documents all input file options. **Must be updated when changing input file syntax or adding new features.**
152+
153+
### API Reference (`documentation/source/reference/`)
154+
- Auto-generated from docstrings using `sphinx.ext.autodoc`
155+
- Each module has a corresponding `.rst` file (e.g., `documentation/source/reference/species/index.rst``rmgpy/species.py`)
156+
- **Maintenance**: Add new modules to the appropriate `index.rst` toctree. Docstrings in code are automatically extracted.
157+
- Uses reStructuredText format with `.. automodule::` directives
158+
159+
### When to Update Documentation
160+
- **New input file options**: Update `documentation/source/users/rmg/input.rst`
161+
- **New public API**: Ensure docstrings exist; add module to `documentation/source/reference/` if new
162+
- **Changed behavior**: Update relevant user guide section
163+
- **New features**: Add to `documentation/source/users/rmg/features.rst` or create and link to new `.rst` file
164+
165+
## Pull Request Review Guidance
166+
### Review Priorities
167+
- Verify changed behavior is covered by tests, or request targeted tests for uncovered paths.
168+
- Check that user-facing changes include required documentation updates (especially input syntax in `documentation/source/users/rmg/input.rst`).
169+
- Confirm Cython changes are complete (`.pyx`/`.pxd` parity, required setup wiring, and likely rebuild impact).
170+
- Watch for performance regressions in hot paths (`rmgpy/molecule/`, `rmgpy/solver/`, kinetics generation loops).
171+
172+
### Other checks
173+
- If `environment.yml` or `.conda/meta.yaml` change, verify they are consistent.
174+
- For changes that affect data loading or estimators, verify assumptions against RMG-database integration points in `rmgpy/data/rmg.py` and related loaders.
175+
176+
## Style Guidelines
177+
- Follow PEP 8 for new or modified code, but don't modify code just to fix style
178+
- Docstrings describe purpose, not implementation
179+
- Use `logging` module (not print statements)
180+
- MIT license header required on all source files

0 commit comments

Comments
 (0)