Coverage-dependent thermochemistry for catalysis#2646
Coverage-dependent thermochemistry for catalysis#2646rwest merged 49 commits intoReactionMechanismGenerator:mainfrom
Conversation
Regression Testing Results
Detailed regression test results.Regression test aromatics:Reference: Execution time (DD:HH:MM:SS): 00:00:01:05 aromatics Passed Core Comparison ✅Original model has 15 species. aromatics Failed Edge Comparison ❌Original model has 106 species. Non-identical thermo! ❌
Identical thermo comments: DetailsObservables Test Case: Aromatics Comparison✅ All Observables varied by less than 0.500 on average between old model and new model in all conditions! aromatics Passed Observable Testing ✅Regression test liquid_oxidation:Reference: Execution time (DD:HH:MM:SS): 00:00:02:08 liquid_oxidation Failed Core Comparison ❌Original model has 37 species. Non-identical kinetics! ❌
kinetics: liquid_oxidation Failed Edge Comparison ❌Original model has 202 species. Non-identical kinetics! ❌
kinetics: Non-identical kinetics! ❌
kinetics: DetailsObservables Test Case: liquid_oxidation Comparison✅ All Observables varied by less than 0.100 on average between old model and new model in all conditions! liquid_oxidation Passed Observable Testing ✅Regression test nitrogen:Reference: Execution time (DD:HH:MM:SS): 00:00:01:22 nitrogen Passed Core Comparison ✅Original model has 41 species. nitrogen Passed Edge Comparison ✅Original model has 132 species. DetailsObservables Test Case: NC Comparison✅ All Observables varied by less than 0.200 on average between old model and new model in all conditions! nitrogen Passed Observable Testing ✅Regression test oxidation:Reference: Execution time (DD:HH:MM:SS): 00:00:02:22 oxidation Passed Core Comparison ✅Original model has 59 species. oxidation Passed Edge Comparison ✅Original model has 230 species. DetailsObservables Test Case: Oxidation Comparison✅ All Observables varied by less than 0.500 on average between old model and new model in all conditions! oxidation Passed Observable Testing ✅Regression test sulfur:Reference: Execution time (DD:HH:MM:SS): 00:00:00:54 sulfur Passed Core Comparison ✅Original model has 27 species. sulfur Failed Edge Comparison ❌Original model has 89 species. DetailsObservables Test Case: SO2 Comparison✅ All Observables varied by less than 0.100 on average between old model and new model in all conditions! sulfur Passed Observable Testing ✅Regression test superminimal:Reference: Execution time (DD:HH:MM:SS): 00:00:00:35 superminimal Passed Core Comparison ✅Original model has 13 species. superminimal Passed Edge Comparison ✅Original model has 18 species. Regression test RMS_constantVIdealGasReactor_superminimal:Reference: Execution time (DD:HH:MM:SS): 00:00:02:24 RMS_constantVIdealGasReactor_superminimal Passed Core Comparison ✅Original model has 13 species. RMS_constantVIdealGasReactor_superminimal Passed Edge Comparison ✅Original model has 13 species. DetailsObservables Test Case: RMS_constantVIdealGasReactor_superminimal Comparison✅ All Observables varied by less than 0.100 on average between old model and new model in all conditions! RMS_constantVIdealGasReactor_superminimal Passed Observable Testing ✅Regression test RMS_CSTR_liquid_oxidation:Reference: Execution time (DD:HH:MM:SS): 00:00:06:07 RMS_CSTR_liquid_oxidation Failed Core Comparison ❌Original model has 37 species. RMS_CSTR_liquid_oxidation Failed Edge Comparison ❌Original model has 206 species. DetailsObservables Test Case: RMS_CSTR_liquid_oxidation Comparison✅ All Observables varied by less than 0.100 on average between old model and new model in all conditions! RMS_CSTR_liquid_oxidation Passed Observable Testing ✅Regression test fragment:Reference: Execution time (DD:HH:MM:SS): 00:00:00:40 fragment Passed Core Comparison ✅Original model has 10 species. fragment Passed Edge Comparison ✅Original model has 33 species. DetailsObservables Test Case: fragment Comparison✅ All Observables varied by less than 0.100 on average between old model and new model in all conditions! fragment Passed Observable Testing ✅Regression test RMS_constantVIdealGasReactor_fragment:Reference: Execution time (DD:HH:MM:SS): 00:00:03:03 RMS_constantVIdealGasReactor_fragment Passed Core Comparison ✅Original model has 10 species. RMS_constantVIdealGasReactor_fragment Passed Edge Comparison ✅Original model has 27 species. DetailsObservables Test Case: RMS_constantVIdealGasReactor_fragment Comparison✅ All Observables varied by less than 0.100 on average between old model and new model in all conditions! RMS_constantVIdealGasReactor_fragment Passed Observable Testing ✅beep boop this comment was written by a bot 🤖 |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2646 +/- ##
==========================================
- Coverage 54.86% 54.83% -0.03%
==========================================
Files 125 125
Lines 37050 37091 +41
==========================================
+ Hits 20326 20340 +14
- Misses 16724 16751 +27 ☔ View full report in Codecov by Sentry. |
|
This pull request is being automatically marked as stale because it has not received any interaction in the last 90 days. Please leave a comment if this is still a relevant pull request, otherwise it will automatically be closed in 30 days. |
|
This pull request is being automatically marked as stale because it has not received any interaction in the last 90 days. Please leave a comment if this is still a relevant pull request, otherwise it will automatically be closed in 30 days. |
|
This pull request is being automatically marked as stale because it has not received any interaction in the last 90 days. Please leave a comment if this is still a relevant pull request, otherwise it will automatically be closed in 30 days. |
|
This pull request is being automatically marked as stale because it has not received any interaction in the last 90 days. Please leave a comment if this is still a relevant pull request, otherwise it will automatically be closed in 30 days. |
Previously the as_dict and the __repr__ would both return thermo_coverage_dependence={}
for absolutely everything.
Now if it starts as None, it stays None.
The on-disk/YAML format for enthalpy-coefficients/entropy-coefficients changed:
Old: {'class': 'np_array', 'object': [<Enthalpy>, ...]}
New: [{'class': 'ScalarQuantity', 'value': ..., 'units': '...'}, ...]
The default_flow_style=None will let it use a single line for things like [1.3, 4.0, 4.45]. Which should look more like we expected. It's a bit clunky that we have to read the yaml, modify the dicts, and dump the yaml, but this should make the changes less obnoxious.
Now it just modifies the part of the yaml file that has changed, instead of reading and writing the whole thing. Will probably still do some refactoring, but making an intermediate commit to check it's working so far. Second commit: (squashed) A refactor of the coverage-dependence-thermo to cantera yaml code. Moved the _add_coverage_dependence_to_cantera_yaml function, and made it pass strings instead of dictionaries.
|
I changed the way we edit the cantera yaml file. Now it makes minimal changes - most of the file remains intact. Here's the new diff between the non-cov-dep and the cov-dep: diff temp/base_rmg_run/cantera/chem_annotated.yaml temp/cov_dep_rmg_run/cantera/chem_annotated.yaml
5c5
< date: Thu, 09 Apr 2026 18:25:54 -0400
---
> date: Thu, 09 Apr 2026 18:32:50 -0400
24c24,25
< thermo: ideal-surface
---
> thermo: coverage-dependent-surface
> reference-state-coverage: 0.11
526a528,533
> coverage-dependencies:
> COX(23):
> model: polynomial
> enthalpy-coefficients: [30103.426817162992, -31164.765583152708, 85871.95470280468]
> entropy-coefficients: [10.70987300225991, -6.252250185103083, -15.72711080512041]
> units: {energy: J, quantity: mol}Sevy's notebook in #2918 seems to show it still works. |
bjkreitz
left a comment
There was a problem hiding this comment.
All looks good to me. Thanks for pushing it over the finish line, Richard!
9cc2cfd
into
ReactionMechanismGenerator:main
When surface species have thermo_coverage_dependence set (from PR #2646), CanteraWriter1 now writes coverage-dependencies into the species entries and switches the surface phase thermo from 'ideal-surface' to 'coverage-dependent-surface', adding the required reference-state-coverage. The new build_coverage_dependencies() helper resolves the adjacency-list keys in thermo_coverage_dependence to Chemkin-style species identifiers, converting ScalarQuantity coefficients to SI float values. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When surface species have thermo_coverage_dependence set (from PR #2646), CanteraWriter2 now writes coverage-dependencies into the species entries (in species_to_dict) and switches the surface phase thermo from 'ideal-surface' to 'coverage-dependent-surface', adding the required reference-state-coverage field. Species names in coverage-dependencies keys use the same get_label() format as the rest of CanteraWriter2's output, consistent with how dependent species are referenced throughout that file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Regression Testing Results
Detailed regression test results.Regression test aromatics:Reference: Execution time (DD:HH:MM:SS): 00:00:00:54 aromatics Passed Core Comparison ✅Original model has 15 species. aromatics Failed Edge Comparison ❌Original model has 106 species. Non-identical thermo! ❌
thermo: Thermo group additivity estimation: group(Cs-(Cds-Cds)CsCsH) + group(Cs-(Cds-Cds)CsCsH) + group(Cs-(Cds-Cds)(Cds-Cds)CsH) + group(Cs-(Cds-Cds)CsHH) + group(Cds-CdsCsCs) + group(Cds-CdsCsH) + group(Cds-CdsCsH) + group(Cds-CdsCsH) + polycyclic(s3_4_5_ene_3) + polycyclic(s2_4_5_diene_1_5) + polycyclic(s2_5_5_diene_1_5) - ring(Cyclobutene) - ring(Cyclopentene) - ring(Cyclopentene) + radical(cyclopentene-allyl) Non-identical thermo! ❌
thermo: Thermo group additivity estimation: group(Cs-(Cds-Cds)CsCsH) + group(Cs-(Cds-Cds)(Cds-Cds)CsH) + group(Cs-(Cds-Cds)(Cds-Cds)CsH) + group(Cs-CsCsHH) + group(Cds-CdsCsCs) + group(Cds-CdsCsH) + group(Cds-CdsCsH) + group(Cds-CdsCsH) + Estimated bicyclic component: polycyclic(s2_3_5_ane) - ring(Cyclopropane) - ring(Cyclopentane) + ring(Cyclopentene) + ring(Cyclopropane) + polycyclic(s2_3_6_ene_1) + polycyclic(s3_5_6_diene_1_5) - ring(Cyclopropane) - ring(Cyclopentene) - ring(Cyclohexene) + radical(cyclopentene-4) Non-identical thermo! ❌
thermo: Thermo group additivity estimation: group(Cs-CsCsCsH) + group(Cs-(Cds-Cds)CsCsH) + group(Cs-(Cds-Cds)CsCsH) + group(Cs-(Cds-Cds)CsHH) + group(Cds- Cds(Cds-Cds)Cs) + group(Cds-CdsCsH) + group(Cds-CdsCsH) + group(Cds-Cds(Cds-Cds)H) + polycyclic(s2_3_5_ene_1) + polycyclic(s2_3_6_ene_1) + Estimated bicyclic component: polycyclic(s3_5_6_ane) - ring(Cyclopentane) - ring(Cyclohexane) + ring(Cyclopentene) + ring(Cyclohexene) - ring(Cyclopropane) - ring(Cyclopentene) - ring(Cyclohexene) + radical(cyclopentene-allyl) Non-identical kinetics! ❌
kinetics: Non-identical kinetics! ❌
kinetics: Non-identical kinetics! ❌
kinetics: Non-identical kinetics! ❌
kinetics: DetailsObservables Test Case: Aromatics Comparison✅ All Observables varied by less than 0.500 on average between old model and new model in all conditions! aromatics Passed Observable Testing ✅Regression test liquid_oxidation:Reference: Execution time (DD:HH:MM:SS): 00:00:01:59 liquid_oxidation Passed Core Comparison ✅Original model has 37 species. liquid_oxidation Failed Edge Comparison ❌Original model has 214 species. Non-identical kinetics! ❌
kinetics: DetailsObservables Test Case: liquid_oxidation Comparison✅ All Observables varied by less than 0.100 on average between old model and new model in all conditions! liquid_oxidation Passed Observable Testing ✅Regression test nitrogen:Reference: Execution time (DD:HH:MM:SS): 00:00:01:03 nitrogen Passed Core Comparison ✅Original model has 41 species. nitrogen Failed Edge Comparison ❌Original model has 133 species. Non-identical thermo! ❌
thermo: Thermo group additivity estimation: group(O2s-CdN3d) + group(N3d-OCd) + group(Cd-HN3dO) + ring(oxirene) + radical(CdJ-NdO) Non-identical kinetics! ❌
kinetics: DetailsObservables Test Case: NC Comparison✅ All Observables varied by less than 0.200 on average between old model and new model in all conditions! nitrogen Passed Observable Testing ✅Regression test oxidation:Reference: Execution time (DD:HH:MM:SS): 00:00:01:45 oxidation Passed Core Comparison ✅Original model has 59 species. oxidation Passed Edge Comparison ✅Original model has 230 species. DetailsObservables Test Case: Oxidation Comparison✅ All Observables varied by less than 0.500 on average between old model and new model in all conditions! oxidation Passed Observable Testing ✅Errors occurred during observable testing
WARNING:root:Initial mole fractions do not sum to one; normalizing.
|
Motivation or Problem
This PR adds in coverage dependent thermodynamic models for heterogeneous catalysis modeling. An adsorbate's enthalpy and entropy should be affected by other adsorbates around it. The PR enables RMG to use a polynomial model to estimate the change of an adsorbate's enthalpy or entropy based on the coverage of other adsorbates on the catalyst surface. By doing this, a Cantera yaml file with thermodynamic coverage dependent data can be generated at the end of a RMG simulation, and it can be used by Cantera (>=3.0) to run PFR simulation. RMG looks into the database to read the thermo coverage dependent models.
Description of Changes
surface.pyx file is modified to change the species enthalpy and entropy based on the coverage dependent (polynomial) models in the database.
nasa.pyx, wilhoit.pyx, and thermodata.pyx are all modified to be able to save the thermo coverage dependent model for each species.
main.py is modified to be able to incorporate thermo coverage dependence modeling as an option and be able to write Cantera yaml file with thermo coverage models in.
Testing
Unit tests are added in thermo and solver folders to test if a species with thermo coverage dependent model can be created and whether the simulation can be run.
To further test the effect to the model generation, a thermo database is made up with the thermo coverage-dependent models, and the data base was used to make a CPOX model on Pt. In the CPOX on Pt model, OX self interaction and COX self interaction are included. The model was then run through a PFR simulation with Cantera 3.0, a significant drop of coverage of COX on the surface was observed, and therefore validate the code modification. Test files are attached here.
test.zip
Reviewer Tips
Please try to pull the changes from this branch and used the database provided in the test.zip to generate a model of your own choice see if it makes any difference to your model compared to without thermo cov dependent model. You can also generate a model with the RMG input file provided in the test.zip, then in the input file turn
thermoCoverageDependenceto False to generate another model without coverage dependence. Then use simultion.py in test.zip to run simulations for the two RMG models generated to test if there is any difference in the simulation results.