diff --git a/README.md b/README.md index 5f47f2b1..36f5a8e7 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,43 @@ -## - -
- -[![PyPI](https://img.shields.io/pypi/v/overreact)](https://pypi.org/project/overreact/) -[![Python Versions](https://img.shields.io/pypi/pyversions/overreact)](https://pypi.org/project/overreact/) -[![CI](https://github.com/geem-lab/overreact/actions/workflows/python-package.yml/badge.svg)](https://github.com/geem-lab/overreact/actions/workflows/python-package.yml) -[![Coverage](https://codecov.io/gh/geem-lab/overreact/branch/main/graph/badge.svg?token=4WAVXCRXY8)](https://codecov.io/gh/geem-lab/overreact) -[![License](https://img.shields.io/github/license/geem-lab/overreact)](https://github.com/geem-lab/overreact/blob/main/LICENSE) - -[![User guide](https://img.shields.io/badge/user%20guide-available-blue)](https://geem-lab.github.io/overreact-guide/) -[![GitHub Discussions](https://img.shields.io/github/discussions/geem-lab/overreact)](https://github.com/geem-lab/overreact/discussions) -[![GitHub issues](https://img.shields.io/github/issues-raw/geem-lab/overreact)](https://github.com/geem-lab/overreact/issues) - -[![downloads/month](https://pepy.tech/badge/overreact/month)](https://pepy.tech/project/overreact) -[![total downloads](https://pepy.tech/badge/overreact)](https://pepy.tech/project/overreact) - -[![DOI](https://zenodo.org/badge/214332027.svg)](https://zenodo.org/badge/latestdoi/214332027) - -[![Made in Brazil 🇧🇷](https://img.shields.io/badge/made%20in-Brazil-009c3b)](https://github.com/geem-lab/overreact#funding) - -
- -
- overreact -
- -## +--- +

PyPI Python Versions License

+ +

User guide GitHub
+Discussions GitHub
+issues

+ +

downloads/month total downloads

+ +

DOI

+ +

Made in Brazil
+🇧🇷

+ +
overreact
+--- **overreact** is a **library** and a **command-line tool** for building and analyzing homogeneous **microkinetic models** from **first-principles diff --git a/docs/overreact.html b/docs/overreact.html index 08ca9df8..537deaa3 100644 --- a/docs/overreact.html +++ b/docs/overreact.html @@ -48,14 +48,10 @@

Contents

@@ -87,34 +83,48 @@

Submodules

overreact

-

#

- -
- -[![PyPI](https://img.shields.io/pypi/v/overreact)](https://pypi.org/project/overreact/) -[![Python Versions](https://img.shields.io/pypi/pyversions/overreact)](https://pypi.org/project/overreact/) -[![CI](https://github.com/geem-lab/overreact/actions/workflows/python-package.yml/badge.svg)](https://github.com/geem-lab/overreact/actions/workflows/python-package.yml) -[![Coverage](https://codecov.io/gh/geem-lab/overreact/branch/main/graph/badge.svg?token=4WAVXCRXY8)](https://codecov.io/gh/geem-lab/overreact) -[![License](https://img.shields.io/github/license/geem-lab/overreact)](https://github.com/geem-lab/overreact/blob/main/LICENSE) - -[![User guide](https://img.shields.io/badge/user%20guide-available-blue)](https://geem-lab.github.io/overreact-guide/) -[![GitHub Discussions](https://img.shields.io/github/discussions/geem-lab/overreact)](https://github.com/geem-lab/overreact/discussions) -[![GitHub issues](https://img.shields.io/github/issues-raw/geem-lab/overreact)](https://github.com/geem-lab/overreact/issues) - -[![downloads/month](https://pepy.tech/badge/overreact/month)](https://pepy.tech/project/overreact) -[![total downloads](https://pepy.tech/badge/overreact)](https://pepy.tech/project/overreact) - -[![DOI](https://zenodo.org/badge/214332027.svg)](https://zenodo.org/badge/latestdoi/214332027) - -[![Made in Brazil 🇧🇷](https://img.shields.io/badge/made%20in-Brazil-009c3b)](https://github.com/geem-lab/overreact#funding) - -
- -
- overreact -
- -

#

+

+ +

PyPI Python Versions License

+ +

User guide GitHub
+Discussions GitHub
+issues

+ +

downloads/month total downloads

+ +

DOI

+ +

Made in Brazil
+🇧🇷

+ +
overreact
+ +

overreact is a library and a command-line tool for building and analyzing homogeneous microkinetic models from first-principles diff --git a/docs/search.js b/docs/search.js index 4c4d5e82..d7a12e46 100644 --- a/docs/search.js +++ b/docs/search.js @@ -1,6 +1,6 @@ window.pdocSearch = (function(){ /** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o#\n\n

\n\n[![PyPI](https://img.shields.io/pypi/v/overreact)](https://pypi.org/project/overreact/)\n[![Python Versions](https://img.shields.io/pypi/pyversions/overreact)](https://pypi.org/project/overreact/)\n[![CI](https://github.com/geem-lab/overreact/actions/workflows/python-package.yml/badge.svg)](https://github.com/geem-lab/overreact/actions/workflows/python-package.yml)\n[![Coverage](https://codecov.io/gh/geem-lab/overreact/branch/main/graph/badge.svg?token=4WAVXCRXY8)](https://codecov.io/gh/geem-lab/overreact)\n[![License](https://img.shields.io/github/license/geem-lab/overreact)](https://github.com/geem-lab/overreact/blob/main/LICENSE)\n\n[![User guide](https://img.shields.io/badge/user%20guide-available-blue)](https://geem-lab.github.io/overreact-guide/)\n[![GitHub Discussions](https://img.shields.io/github/discussions/geem-lab/overreact)](https://github.com/geem-lab/overreact/discussions)\n[![GitHub issues](https://img.shields.io/github/issues-raw/geem-lab/overreact)](https://github.com/geem-lab/overreact/issues)\n\n[![downloads/month](https://pepy.tech/badge/overreact/month)](https://pepy.tech/project/overreact)\n[![total downloads](https://pepy.tech/badge/overreact)](https://pepy.tech/project/overreact)\n\n[![DOI](https://zenodo.org/badge/214332027.svg)](https://zenodo.org/badge/latestdoi/214332027)\n\n[![Made in Brazil \ud83c\udde7\ud83c\uddf7](https://img.shields.io/badge/made%20in-Brazil-009c3b)](https://github.com/geem-lab/overreact#funding)\n\n
\n\n
\n \"overreact\"\n
\n\n

#

\n\n

overreact is a library and a command-line tool for building and\nanalyzing homogeneous microkinetic models from first-principles\ncalculations:

\n\n
In [1]: from overreact import api\n\nIn [2]: api.get_k("S -> E\u2021 -> S",\n   ...:           {"S": "data/ethane/B97-3c/staggered.out",\n   ...:            "E\u2021": "data/ethane/B97-3c/eclipsed.out"})\nOut[2]: array([8.16880917e+10])\n
\n\n\n\n

\n \n \ud83e\udd14 What is microkinetic modeling?\n \n

\n Microkinetic modeling is a technique used to predict the outcome\n of complex chemical reactions.\n It can be used\n to investigate the catalytic transformations\n of molecules.\n overreact makes it easy to create\n and analyze microkinetic models built\n from computational chemistry data.\n

\n

\n\n


\n\n

\n \n \ud83e\uddd0 What do you mean by first-principles calculations?\n \n

\n We use the term first-principles calculations to refer to\n calculations performed using quantum chemical modern methods such as\n Wavefunction\n and\n Density Functional\n theories.\n For instance, the three-line example code above calculates the rate of methyl rotation in ethane (at\n B97-3c).\n (Rather surprisingly, the error found is less than 2%\n when compared to available experimental results.)\n

\n

\n\n


\n\n

overreact uses precise thermochemical partition funtions, tunneling\ncorrections and data is parsed directly from computational chemistry\noutput files thanks to cclib (see the\nlist of its supported programs).

\n\n

Installation

\n\n

overreact is a Python package, so you can easily install it with\npip:

\n\n
$ pip install "overreact[cli,fast]"\n
\n\n

See the\ninstallation guide\nfor more details.

\n\n
\n

\ud83d\ude80 Where to go from here? Take a look at the\n short introduction.\n Or see\n below\n for more guidance.

\n
\n\n

Citing overreact

\n\n

If you use overreact in your research, please cite:

\n\n
\n

F. S. S. Schneider and G. F. Caramori. _geem-lab/overreact: a tool for\n creating and analyzing microkinetic models built from computational chemistry\n data, v1.0.2_. 2021.\n DOI:10.5281/zenodo.5730603.\n Freely available at: <https://github.com/geem-lab/overreact>.

\n
\n\n

Here's the reference in BibTeX format:

\n\n
@misc{overreact2021,\n  howpublished = {\\url{https://github.com/geem-lab/overreact}}\n  year = {2021},\n  author = {Schneider, F. S. S. and Caramori, G. F.},\n  title = {\n    \\textbf{geem-lab/overreact}: a tool for creating and analyzing\n    microkinetic models built from computational chemistry data, v1.0.2\n  },\n  doi = {10.5281/zenodo.5730603},\n  url = {https://zenodo.org/record/5730603},\n  publisher = {Zenodo},\n  copyright = {Open Access}\n}\n
\n\n
\n

\u270f\ufe0f A paper describing overreact is currently being prepared. When it\n is published, the above BibTeX entry will be updated.

\n
\n\n

License

\n\n

overreact is open-source, released under the permissive MIT license. See\nthe LICENSE agreement.

\n\n

Funding

\n\n

This project was developed at the GEEM lab\n(Federal University of Santa Catarina, Brazil), and was\npartially funded by the\nBrazilian National Council for Scientific and Technological Development (CNPq),\ngrant number 140485/2017-1.

\n"}, {"fullname": "overreact.api", "modulename": "overreact.api", "type": "module", "doc": "

This module contains the high-level application programming interface.

\n\n

If you intend to use overreact as a library in a project, you should\nprobably start here.

\n"}, {"fullname": "overreact.api.get_k", "modulename": "overreact.api", "qualname": "get_k", "type": "function", "doc": "

Obtain reaction rate constants for a given reaction scheme.

\n\n
Parameters
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • compounds (dict-like, optional):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • bias (array-like, optional):\nEnergy to be added to free energies.
  • \n
  • tunneling (str or None, optional):\nChoose between \"eckart\", \"wigner\" or None (or \"none\").
  • \n
  • qrrho (bool or tuple-like, optional):\nApply both the quasi-rigid rotor harmonic oscillator (QRRHO)\napproximations of M. Head-Gordonand others (enthalpy correction, see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\nand S. Grimme (entropy correction, see\nTheory. Chem. Eur. J., 2012, 18: 9955-9964)\non top of the classical RRHO.
  • \n
  • scale (str, optional):\nReaction rate units. Possible values are \"cm3 mol-1 s-1\",\n\"l mol-1 s-1\", \"m3 mol-1 s-1\", \"cm3 particle-1 s-1\", \"mmHg-1 s-1\" and\n\"atm-1 s-1\".
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
  • delta_freeenergies (array-like, optional):\nUse this instead of obtaining delta free energies from the compounds.
  • \n
  • molecularity (array-like, optional):\nReaction order, i.e., number of molecules that come together to react.\nIf set, this is used to calculate delta_moles for\noverreact.thermo.equilibrium_constant, which effectively calculates a solution\nequilibrium constant between reactants and the transition state for\ngas phase data. You should set this to None if your free energies\nwere already adjusted for solution Gibbs free energies.
  • \n
  • volume (float, optional):\nMolar volume.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Notes
\n\n

Some symbols are accepted as alternatives in \"scale\": \"M-1\", \"ml\" and\n\"torr-1\" are understood as \"l mol-1\", \"cm3\" and \"mmHg-1\", respectively.

\n\n
Examples
\n\n

Below is an example of an estimate for the rate of methyl rotation in\nethane (a trivial attempt to reproduce\nScience, 2006, 313, 5795, 1951-1955).\nHow many turns it does per second?

\n\n
>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> get_k(model.scheme, model.compounds)\narray([8.16e+10])\n>>> get_k(model.scheme, model.compounds, qrrho=(False, True))\narray([8.24968117e+10])\n>>> get_k(model.scheme, model.compounds, qrrho=False)\narray([8.26909266e+10])\n>>> get_k(model.scheme, model.compounds, tunneling="wigner")\narray([7.99e+10])\n>>> get_k(model.scheme, model.compounds, tunneling=None)\narray([7.35e+10])\n
\n\n

The calculated value is off by less than 2% from the experimental value\n(\\( \\frac{1}{12 \\times 10^{-12}} \\text{s}^{-1} = 8.33 \\times 10^{10} \\text{s}^{-1} \\)).\nWe use Eckart tunneling by default, but see the effect of changing it\nabove.

\n\n

The units of the returned reaction rate constants can be selected for\nnon-unimolecular processes. The following is an attempt to reproduce\nJ Atmos Chem, 1996 23, 37\u201349 for\nthe reaction of proton-withdrawal by a chloride radical from the methane\nmolecule\n\\( \\ce{CH4 + \\cdot Cl -> [H3C\\cdots H\\cdots Cl]^\\ddagger -> H3C\\cdot + HCl} \\):

\n\n
>>> model = rx.parse_model("data/tanaka1996/UMP2/cc-pVTZ/model.jk")\n>>> get_k(model.scheme, model.compounds, temperature=300,\n...       scale="cm3 particle-1 s-1")\narray([9.60e-14])\n
\n\n

(By the way, according to the Jet Propulsion Laboratory,\nPublication No. 19-5,\nthe experimental reaction rate constant for this reaction is\n\\( 1.0 \\times 10^{-13} \\text{cm}^3 \\text{particle}^{-1} \\text{s}^{-1} \\).)

\n\n

The returned units are \"M-1 s-1\" by default:

\n\n
>>> get_k(model.scheme, model.compounds) \\\n... == get_k(model.scheme, model.compounds, scale="l mol-1 s-1")\narray([ True])\n
\n\n

You can also turn the tunneling correction off by using the string \"none\":

\n\n
>>> get_k(model.scheme, model.compounds, tunneling="none") \\\n... == get_k(model.scheme, model.compounds, tunneling=None)\narray([ True])\n
\n\n

You can set a simple energy bias, either as a constant or compound-wise:

\n\n
>>> get_k(model.scheme, model.compounds, bias=1.0 * constants.kcal,\n...       temperature=300.0, scale="cm3 particle-1 s-1")\narray([5.14e-13])\n>>> get_k(model.scheme, model.compounds,\n...       bias=np.array([0.0, 0.0, -1.4, 0.0, 0.0]) * constants.kcal,\n...       temperature=300.0, scale="cm3 particle-1 s-1")\narray([1.1e-12])\n
\n", "signature": "(\n scheme: overreact.core.Scheme,\n compounds: Optional[dict] = None,\n bias: float = 0.0,\n tunneling: str = 'eckart',\n qrrho: Union[bool, tuple[bool, bool]] = True,\n scale: str = 'l mol-1 s-1',\n temperature: float = 298.15,\n pressure: float = 101325.0,\n delta_freeenergies: Optional[float] = None,\n molecularity: Optional[float] = None,\n volume: Optional[float] = None\n) -> float", "funcdef": "def"}, {"fullname": "overreact.api.get_kappa", "modulename": "overreact.api", "qualname": "get_kappa", "type": "function", "doc": "

Obtain tunneling transmission coefficients at a given temperature.

\n\n

One tunneling transmission coefficient is calculated for each reaction. If\na reaction lacks a transition state (i.e., a half-equilibrium reaction),\nits transmission coefficient is set to unity.

\n\n
Parameters
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • method (str or None, optional):\nChoose between \"eckart\", \"wigner\" or None (or \"none\").
  • \n
  • qrrho (bool, optional):\nApply both the quasi-rigid rotor harmonic oscillator (QRRHO)\napproximations of M. Head-Gordon and others (enthalpy correction, see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\nand S. Grimme (entropy correction, see\nTheory. Chem. Eur. J., 2012, 18: 9955-9964)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Raises
\n\n
    \n
  • ValueError: If method is not supported.
  • \n
\n\n
Examples
\n\n

Below is an example of an estimate of how much quantum tunneling\ncontributes to the rate of methyl rotation in ethane (see\nScience, 2006, 313, 5795, 1951-1955\nfor some interesting experimental data on this reaction).

\n\n
>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> kappa = get_kappa(model.scheme, model.compounds)\n>>> kappa\narray([1.110])\n>>> get_kappa(model.scheme, model.compounds, method="none")\narray([1.0])\n>>> get_kappa(model.scheme, model.compounds, method="none") \\\n... == get_kappa(model.scheme, model.compounds, method=None)\narray([ True])\n
\n\n

You can calculate each piece of the reaction rate constant by hand,\nif you want. Just make sure that you don't calculate the tunneling\ncoefficient twice:

\n\n
>>> kappa * get_k(model.scheme, model.compounds, tunneling=None)\narray([8.e+10])\n
\n", "signature": "(\n scheme: overreact.core.Scheme,\n compounds: dict,\n method: str = 'eckart',\n qrrho: bool = True,\n temperature: float = 298.15\n)", "funcdef": "def"}, {"fullname": "overreact.api.get_freeenergies", "modulename": "overreact.api", "qualname": "get_freeenergies", "type": "function", "doc": "

Obtain free energies for compounds at a given temperature and pressure.

\n\n
Parameters
\n\n
    \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • bias (array-like, optional):\nEnergy to be added to free energies.
  • \n
  • environment (str or None, optional):\nChoose between \"gas\" and a solvent. This is chosen for you by default,\nbased on the names of each compound. If given, all compounds will\nhave the same behavior.
  • \n
  • method (str, optional):\nThis is a placeholder for future functionality.\nThere are plans to implement more sophisticated methods for calculating\nentropies such as in\nPhys. Chem. Chem. Phys., 2019, 21, 18920-18929\nand\nJ. Chem. Theory Comput. 2019, 15, 5, 3204\u20133214.\nHead over to the\ndiscussions if\nyou're interested and would like to contribute.\nLeave this as \"standard\" for now.
  • \n
  • qrrho (bool or tuple-like, optional):\nApply both the quasi-rigid rotor harmonic oscillator (QRRHO)\napproximations of M. Head-Gordon and others (enthalpy correction, see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\nand S. Grimme (entropy correction, see\nTheory. Chem. Eur. J., 2012, 18: 9955-9964)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Examples
\n\n
>>> import overreact as rx\n>>> from overreact import _constants as constants\n>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> freeenergies = get_freeenergies(model.compounds, qrrho=(False, True))\n>>> (freeenergies - freeenergies.min()) / constants.kcal\narray([0. , 2.62281461])\n>>> freeenergies = get_freeenergies(model.compounds)\n>>> (freeenergies - freeenergies.min()) / constants.kcal\narray([0. , 2.62862818])\n
\n\n

You can consider all compounds as solvated if you want:

\n\n
>>> sol_freeenergies = get_freeenergies(model.compounds, environment="solvent")\n>>> (sol_freeenergies - freeenergies) / constants.kcal\narray([1.89432845, 1.89432845])\n
\n\n

You can set a simple energy bias, either as a constant or compound-wise:

\n\n
>>> get_freeenergies(model.compounds, bias=1.0) - freeenergies\narray([1., 1.])\n>>> get_freeenergies(model.compounds, bias=-1.0) - freeenergies\narray([-1., -1.])\n>>> get_freeenergies(model.compounds, bias=[1.0, -1.0]) - freeenergies\narray([ 1., -1.])\n
\n", "signature": "(\n compounds: dict,\n bias: float = 0.0,\n environment: Optional[str] = None,\n method: str = 'standard',\n qrrho: Union[bool, tuple[bool, bool]] = True,\n temperature: float = 298.15,\n pressure: float = 101325.0\n)", "funcdef": "def"}, {"fullname": "overreact.api.get_entropies", "modulename": "overreact.api", "qualname": "get_entropies", "type": "function", "doc": "

Obtain entropies for compounds at a given temperature and pressure.

\n\n
Parameters
\n\n
    \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • environment (str or None, optional):\nChoose between \"gas\" and a solvent. This is chosen for you by default,\nbased on the names of each compound (e.g. A(g) or A is gas,\nA(w) or A(...) is solvated). In case this is given, all compounds\nwill have the same behavior.
  • \n
  • method (str, optional):\nThis is a placeholder for future functionality.\nThere are plans to implement more sophisticated methods for calculating\nentropies such as in\nPhys. Chem. Chem. Phys., 2019, 21, 18920-18929\nand\nJ. Chem. Theory Comput. 2019, 15, 5, 3204\u20133214.\nHead over to the\ndiscussions if\nyou're interested and would like to contribute.\nLeave this as \"standard\" for now.
  • \n
  • qrrho (bool, optional):\nApply the quasi-rigid rotor harmonic oscillator (QRRHO) approximation of\nS. Grimme (see\nTheory. Chem. Eur. J., 2012, 18: 9955-9964)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Examples
\n\n
>>> import overreact as rx\n>>> from overreact import _constants as constants\n>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> entropies = get_entropies(model.compounds)\n>>> (entropies - entropies.min()) / constants.calorie\narray([1.4, 0. ])\n
\n\n

You can consider all compounds as solvated if you want:

\n\n
>>> sol_entropies = get_entropies(model.compounds, environment="solvent")\n>>> (sol_entropies - entropies) / constants.calorie\narray([-6.35360874, -6.35360874])\n
\n", "signature": "(\n compounds: dict,\n environment: Optional[str] = None,\n method: str = 'standard',\n qrrho: bool = True,\n temperature: float = 298.15,\n pressure: float = 101325.0\n)", "funcdef": "def"}, {"fullname": "overreact.api.get_enthalpies", "modulename": "overreact.api", "qualname": "get_enthalpies", "type": "function", "doc": "

Obtain enthalpies for compounds at a given temperature.

\n\n
Parameters
\n\n
    \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • qrrho (bool, optional):\nApply the quasi-rigid rotor harmonic oscillator (QRRHO) approximation of\nM. Head-Gordon and others (see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Examples
\n\n
>>> import overreact as rx\n>>> from overreact import _constants as constants\n>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> enthalpies = get_enthalpies(model.compounds)\n>>> (enthalpies - enthalpies.min()) / constants.kcal\narray([0. , 2.20053981])\n
\n\n

The enthalpies at absolute zero can easily be obtained (this is used,\ne.g., in the calculation of the Eckart tunneling coefficient, see\noverreact.tunnel.eckart). We can use this to calculate, for instance,\nthe thermal contributions to the enthalpy:

\n\n
>>> zero_enthalpies = get_enthalpies(model.compounds, temperature=0)\n>>> (enthalpies - zero_enthalpies) / constants.kcal\narray([2.78, 2.50])\n
\n", "signature": "(compounds: dict, qrrho: bool = True, temperature: float = 298.15)", "funcdef": "def"}, {"fullname": "overreact.api.get_internal_energies", "modulename": "overreact.api", "qualname": "get_internal_energies", "type": "function", "doc": "

Obtain internal energies for compounds at a given temperature.

\n\n
Parameters
\n\n
    \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • qrrho (bool, optional):\nApply the quasi-rigid rotor harmonic oscillator (QRRHO) approximation of\nM. Head-Gordon and others (see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Examples
\n\n
>>> import overreact as rx\n>>> from overreact import _constants as constants\n>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> internal_energies = get_internal_energies(model.compounds)\n>>> (internal_energies - internal_energies.min()) / constants.kcal\narray([0. , 2.20053981])\n
\n", "signature": "(compounds: dict, qrrho: bool = True, temperature: float = 298.15)", "funcdef": "def"}, {"fullname": "overreact.coords", "modulename": "overreact.coords", "type": "module", "doc": "

Module dedicated to classifying molecules into point groups.

\n"}, {"fullname": "overreact.coords.find_point_group", "modulename": "overreact.coords", "qualname": "find_point_group", "type": "function", "doc": "

Determine point group of structure.

\n\n
Parameters
\n\n
    \n
  • atommasses (array-like):\nAtomic masses in atomic mass units (amu).
  • \n
  • atomcoords (array-like):\nAtomic coordinates.
  • \n
  • proper_axes (sequence of tuples of int, array-like, optional):\nProper symmetry axes of rotation.
  • \n
  • rtol (float, optional):\nThe relative tolerance parameter (see numpy.isclose).
  • \n
  • atol (float, optional):\nThe absolute tolerance parameter (see numpy.isclose).
  • \n
\n\n
Returns
\n\n
    \n
  • str: Point group symbol.
  • \n
\n\n
Examples
\n\n
>>> find_point_group([1], [[0, 0, 1]])\n'K'\n>>> find_point_group([1, 1], [[0, 0, 1], [0, 0, 0]])\n'D\u221eh'\n>>> find_point_group([1.008, 35.45], [[0, 0, 1], [0, 0, 0]])\n'C\u221ev'\n>>> find_point_group([16, 12, 16], [[1, 0, 1], [1, 0, 0], [1, 0, -1]])\n'D\u221eh'\n>>> find_point_group([16, 12, 32], [[1, 1, 1], [1, 1, 0], [1, 1, -1]])\n'C\u221ev'\n>>> find_point_group([12, 12, 12, 12], [[1, 0, 0],\n...                                     [0, 1, 0],\n...                                     [0, 0, 0],\n...                                     [1, 1, 0]])\n'D4h'\n
\n", "signature": "(atommasses, atomcoords, proper_axes=None, rtol=0.0, atol=0.01)", "funcdef": "def"}, {"fullname": "overreact.coords.symmetry_number", "modulename": "overreact.coords", "qualname": "symmetry_number", "type": "function", "doc": "

Return rotational symmetry number for point group.

\n\n

This function has a set of the most common point groups precomputed, but is\nable to calculate the symmetry number if it is not found in known tables.\nMost precomputed values are from\nTheor Chem Account 2007 118, 813\u2013826.

\n\n
Parameters
\n\n
    \n
  • point_group (str):\nPoint group symbol.
  • \n
\n\n
Returns
\n\n
    \n
  • int: Rotational symmetry number.
  • \n
\n\n
Raises
\n\n
    \n
  • ValueError: If point group is not found in precomputed values.
  • \n
\n\n
Examples
\n\n
>>> symmetry_number("C4")\n4\n>>> symmetry_number("C4") == symmetry_number("C4h")\nTrue\n>>> symmetry_number("C6")\n6\n>>> symmetry_number("C6") == symmetry_number("C6v")\nTrue\n>>> symmetry_number("C6") == symmetry_number("C6h")\nTrue\n>>> symmetry_number("D2") == symmetry_number("Vh")\nTrue\n>>> symmetry_number("D4")\n8\n>>> symmetry_number("D6")\n12\n>>> symmetry_number("D6") == symmetry_number("D6d")\nTrue\n>>> symmetry_number("S6")\n3\n>>> symmetry_number("T")\n12\n
\n", "signature": "(point_group)", "funcdef": "def"}, {"fullname": "overreact.core", "modulename": "overreact.core", "type": "module", "doc": "

Module dedicated to parsing and modeling of chemical reaction networks.

\n"}, {"fullname": "overreact.core.Scheme", "modulename": "overreact.core", "qualname": "Scheme", "type": "class", "doc": "

A descriptor of a chemical reaction network.

\n\n

Mostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.

\n", "bases": "typing.NamedTuple"}, {"fullname": "overreact.core.Scheme.__init__", "modulename": "overreact.core", "qualname": "Scheme.__init__", "type": "function", "doc": "

Create new instance of Scheme(compounds, reactions, is_half_equilibrium, A, B)

\n", "signature": "(\n _cls,\n compounds: Sequence[str],\n reactions: Sequence[str],\n is_half_equilibrium: Sequence[bool],\n A: numpy.ndarray,\n B: numpy.ndarray\n)", "funcdef": "def"}, {"fullname": "overreact.core.Scheme.compounds", "modulename": "overreact.core", "qualname": "Scheme.compounds", "type": "variable", "doc": "

A descriptor of compounds.

\n", "annotation": ": Sequence[str]"}, {"fullname": "overreact.core.Scheme.reactions", "modulename": "overreact.core", "qualname": "Scheme.reactions", "type": "variable", "doc": "

A descriptor of reactions.

\n", "annotation": ": Sequence[str]"}, {"fullname": "overreact.core.Scheme.is_half_equilibrium", "modulename": "overreact.core", "qualname": "Scheme.is_half_equilibrium", "type": "variable", "doc": "

An indicator of whether a reaction is half-equilibrium.

\n", "annotation": ": Sequence[bool]"}, {"fullname": "overreact.core.Scheme.A", "modulename": "overreact.core", "qualname": "Scheme.A", "type": "variable", "doc": "

A matrix of stoichiometric coefficients between reactants and products.

\n", "annotation": ": numpy.ndarray"}, {"fullname": "overreact.core.Scheme.B", "modulename": "overreact.core", "qualname": "Scheme.B", "type": "variable", "doc": "

A matrix of stoichiometric coefficients between reactants and transition states.

\n", "annotation": ": numpy.ndarray"}, {"fullname": "overreact.core.parse_reactions", "modulename": "overreact.core", "qualname": "parse_reactions", "type": "function", "doc": "

Parse a kinetic model as a chemical reaction scheme.

\n\n

This is an essential part of the parsing process.\nSee overreact.io.parse_model other details.

\n\n
Parameters
\n\n
    \n
  • text (str or sequence of str):\nModel description or sequence of lines of it.
  • \n
\n\n
Returns
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.
  • \n
\n\n
Notes
\n\n

The model description should comply with the mini-language for systems of\nreactions. A semi-formal definition of the grammar in\nBackus\u2013Naur form\nis given below:

\n\n
     equation ::= equation_side arrow equation_side\nequation_side ::= coefficient compound ['+' coefficient compound]*\n  coefficient ::= [integers] (defaults to 1)\n     compound ::= mix of printable characters\n        arrow ::= '->' | '<=>' | '<-'\n
\n\n

Blank lines and comments (starting with //) are ignored. Repeated\nreactions are ignored. Furthermore, reactions can be chained one after\nanother and, if a single compound (with either a \u2021 or a # at the end)\nappears alone on one side of a reaction, it's considered a transition\nstate. Transition states have zero lifetime during the simulation.

\n\n
Examples
\n\n

What follows is a rather long tour over the parsing process and its\noutput in general. You can skip it if you are not interested in the\ndetails.

\n\n
>>> scheme = parse_reactions("A -> B  // a direct reaction")\n
\n\n

The reaction above is a direct one (observe that comments are ignored). The\nreturned object has the following attributes:

\n\n
>>> scheme.compounds\n('A', 'B')\n>>> scheme.reactions\n('A -> B',)\n>>> scheme.is_half_equilibrium\n(False,)\n>>> scheme.A\n((-1.,), (1.,))\n>>> scheme.B\n((-1.,), (1.,))\n
\n\n

The same reaction can be specified in reverse order:

\n\n
>>> parse_reactions("B <- A  // reverse reaction of the above")\nScheme(compounds=('A', 'B'),\n       reactions=('A -> B',),\n       is_half_equilibrium=(False,),\n       A=((-1.,), (1.,)),\n       B=((-1.,), (1.,)))\n
\n\n

Equilibria produce twice as many direct reactions, while the $B$ matrix\ndefines an energy relationship for only one of each pair:

\n\n
>>> parse_reactions("A <=> B  // an equilibrium")\nScheme(compounds=('A', 'B'),\n       reactions=('A -> B', 'B -> A'),\n       is_half_equilibrium=(True, True),\n       A=((-1.,  1.),\n          (1., -1.)),\n       B=((-1.,  0.),\n          (1.,  0.)))\n
\n\n

Adding twice the same reaction results in a single reaction being added.\nThis of course also works with equilibria (extra whitespaces are ignored):

\n\n
>>> parse_reactions('''\n...     A <=> B  -> A\n...     A  -> B <=> A\n...     A  -> B <-  A\n...     B <-  A  -> B\n... ''')\nScheme(compounds=('A', 'B'),\n       reactions=('A -> B', 'B -> A'),\n       is_half_equilibrium=(True, True),\n       A=((-1.,  1.),\n          (1., -1.)),\n       B=((-1.,  0.),\n          (1.,  0.)))\n
\n\n

Transition states are specified with a special symbol at the end (either\n\u2021 or #). They are shown among compounds, but the matrix $A$ ensures\nthey'll never have a non-zero rate of formation/consumption. On the other\nhand, they are needed in the $B$ matrix:

\n\n
>>> parse_reactions("A -> A\u2021 -> B")\nScheme(compounds=('A', 'A\u2021', 'B'),\n       reactions=('A -> B',),\n       is_half_equilibrium=(False,),\n       A=((-1.,), (0.,), (1.,)),\n       B=((-1.,), (1.,), (0.,)))\n
\n\n

This gives the same result as above:

\n\n
>>> parse_reactions("A -> A\u2021 -> B <- A\u2021 <- A")\nScheme(compounds=('A', 'A\u2021', 'B'),\n       reactions=('A -> B',),\n       is_half_equilibrium=(False,),\n       A=((-1.,), (0.,), (1.,)),\n       B=((-1.,), (1.,), (0.,)))\n
\n\n

It is possible to define a reaction whose product is the same as the\nreactant. This is found in isomerization processes (e.g., ammonia\ninversion or the methyl rotation in ethane):

\n\n
>>> parse_reactions("S -> E\u2021 -> S")\nScheme(compounds=('S', 'E\u2021'),\n       reactions=('S -> S',),\n       is_half_equilibrium=(False,),\n       A=((0.,), (0.,)),\n       B=((-1.,), (1.,)))\n
\n\n

As such, a column full of zeros in the $A$ matrix corresponds to a reaction\nwith zero net change. As can be seen, overreact allows for very general\nmodels. An interesting feature is that a single transition state can link\nmany different compounds (whether it is useful is a matter of debate):

\n\n
>>> parse_reactions('''\n...     B  -> B\u2021  -> C  // chained reactions and transition states\n...     B\u2021 -> D         // this is a bifurcation\n...     B  -> B'\u2021 -> E  // this is a classical competitive reaction\n...     A  -> B\u2021\n... ''')\nScheme(compounds=('B', 'B\u2021', 'C', 'D', "B'\u2021", 'E', 'A'),\n       reactions=('B -> C', 'B -> D', 'B -> E', 'A -> C', 'A -> D'),\n       is_half_equilibrium=(False, False, False, False, False),\n       A=((-1., -1., -1.,  0.,  0.),\n          (0.,  0.,  0.,  0.,  0.),\n          (1.,  0.,  0.,  1.,  0.),\n          (0.,  1.,  0.,  0.,  1.),\n          (0.,  0.,  0.,  0.,  0.),\n          (0.,  0.,  1.,  0.,  0.),\n          (0.,  0.,  0., -1., -1.)),\n       B=((-1., -1., -1.,  0.,  0.),\n          (1.,  1.,  0.,  1.,  1.),\n          (0.,  0.,  0.,  0.,  0.),\n          (0.,  0.,  0.,  0.,  0.),\n          (0.,  0.,  1.,  0.,  0.),\n          (0.,  0.,  0.,  0.,  0.),\n          (0.,  0.,  0., -1., -1.)))\n
\n\n

The following is a borderline case but both reactions should be considered\ndifferent since they define different processes:

\n\n
>>> parse_reactions('''\n...     A -> A\u2021 -> B\n...     A -> B\n... ''')\nScheme(compounds=('A', 'A\u2021', 'B'),\n       reactions=('A -> B', 'A -> B'),\n       is_half_equilibrium=(False, False),\n       A=((-1., -1.),\n          (0.,  0.),\n          (1.,  1.)),\n       B=((-1., -1.),\n          (1.,  0.),\n          (0.,  1.)))\n
\n\n

The following is correct behavior. In fact, the reactions are badly\ndefined: if more than one transition state are chained, the following\nhappens, which is correct since it's the most physically plausible model\nthat can be extracted. It can be seen as a feature that the product B is\nignored and not the reactant A, since the user would easily see the mistake\nin graphs of concentration over time (the alternative would be no\nreaction happening at all, which is rather cryptic to debug).

\n\n
>>> parse_reactions("A -> A\u2021 -> A'\u2021 -> B")\nScheme(compounds=('A', 'A\u2021', "A'\u2021", 'B'),\n       reactions=("A -> A'\u2021",),\n       is_half_equilibrium=(False,),\n       A=((-1.,), (0.,), (1.,), (0.,)),\n       B=((-1.,), (1.,), (0.,), (0.,)))\n
\n\n

In any case, it's not clear how a reaction barrier be defined in such a\ncase. If you have a use case, don't hesitate to\nopen an issue, we'll be\nhappy to hear from you.

\n", "signature": "(text: Union[str, Sequence[str]]) -> overreact.core.Scheme", "funcdef": "def"}, {"fullname": "overreact.io", "modulename": "overreact.io", "type": "module", "doc": "

Basic I/O operations (such as reading source input files).

\n"}, {"fullname": "overreact.io.parse_model", "modulename": "overreact.io", "qualname": "parse_model", "type": "function", "doc": "

Parse either a source or model input file, whichever is available.

\n\n

A source input file (also known as a .k file) contains all the information needed\nto create a model input file.\nA model input file (also known as a .jk file) is a JSON encoded file with all the\ninformation needed to study microkinetic simulations from first principles.

\n\n

You probably won't need to use model input files directly, they are\nautomatically created based on source input files.\nTake a look at our guide on how to write an source input file.

\n\n

This function attempts to parse a model input file if available. If not, a source\ninput file is parsed and a model input file is generated from it. Extensions are\nguessed if none given (i.e., if only the base name given).

\n\n
Parameters
\n\n
    \n
  • path (str):\nPath to the model or source input file.\nIf the final extension is not .jk or .k, it is guessed.
  • \n
  • force_compile (bool):\nIf True, a .k file will take precedence over any .jk file for reading. A\n.jk file is thus either generated or overwritten. This is sometimes\nneeded to force an update with new data.
  • \n
\n\n
Returns
\n\n
    \n
  • model (immutable dict-like):
  • \n
\n\n
Raises
\n\n
    \n
  • FileNotFoundError: If the model or source input file is not found.
  • \n
\n\n
Examples
\n\n

Some examples of how overreact \"sees\" your data below \ud83d\ude04:

\n\n
>>> model = parse_model("data/ethane/B97-3c/model.jk")\n>>> model.scheme\nScheme(compounds=('S', 'E\u2021'),\n       reactions=('S -> S',),\n       is_half_equilibrium=(False,),\n       A=((0.0,), (0.0,)),\n       B=((-1.0,), (1.0,)))\n>>> model.compounds["S"]\n{'logfile': 'data/ethane/B97-3c/staggered.out',\n 'energy': -209483812.77142256,\n 'mult': 1,\n 'atomnos': (6, 6, 1, 1, 1, 1, 1, 1),\n 'atommasses': (12.011, 12.011, 1.008, 1.008, 1.008, 1.008, 1.008, 1.008),\n 'atomcoords': ((-7.633588, 2.520693, -4.8e-05),\n                ...,\n                (-5.832852, 3.674431, 0.363239)),\n 'vibfreqs': (307.57, 825.42, ..., 3071.11, 3071.45),\n 'vibdisps': (((-1.7e-05, 3.4e-05, 5.4e-05),\n               ...,\n               (-0.011061, -0.030431, -0.027036)))}\n>>> model_from_source = parse_model("data/ethane/B97-3c/model.k",\n...                                 force_compile=True)\n>>> model_from_source == model\nTrue\n>>> model_from_source = parse_model("data/ethane/B97-3c/model")\n>>> model_from_source == model\nTrue\n
\n", "signature": "(path: str, force_compile: bool = False)", "funcdef": "def"}, {"fullname": "overreact.rates", "modulename": "overreact.rates", "type": "module", "doc": "

Module dedicated to the calculation of reaction rate constants.

\n"}, {"fullname": "overreact.rates.eyring", "modulename": "overreact.rates", "qualname": "eyring", "type": "function", "doc": "

Calculate a reaction rate constant.

\n\n

This function uses the Eyring-Evans-Polanyi equation\n from transition state\ntheory :

\n\n

$$k(T) = \\frac{k_\\text{B} T}{h} K^\\ddagger\n = \\frac{k_\\text{B} T}{h}\n \\exp\\left(-\\frac{\\Delta^\\ddagger G^\\circ}{R T}\\right)$$

\n\n

where \\( h \\) is Planck's constant, \\( k_\\text{B} \\) is Boltzmann's\nconstant and \\( T \\) is the absolute temperature.

\n\n
Parameters
\n\n
    \n
  • delta_freeenergy (array-like):\nDelta Gibbs activation free energies. This assumes values were already\ncorrected for a one molar reference state (if applicable).
  • \n
  • molecularity (array-like, optional):\nReaction order, i.e., number of molecules that come together to react.\nIf set, this is used to calculate delta_moles for\nequilibrium_constant, which effectively calculates a solution\nequilibrium constant between reactants and the transition state for\ngas phase data. You should set this to None if your free energies\nwere already adjusted for solution Gibbs free energies.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
  • volume (float, optional):\nMolar volume. This is passed on to equilibrium_constant.
  • \n
\n\n
Returns
\n\n
    \n
  • k (array-like):\nReaction rate constant(s). By giving energies in one molar reference\nstate, returned units are then accordingly given, e.g. \"l mol-1 s-1\"\nif second-order, etc.
  • \n
\n\n
Notes
\n\n

This function uses equilibrium_constant internally to calculate the\nequilibrium constant between reactants and the transition state.

\n\n
Examples
\n\n

The following are examples from\nThermochemistry in Gaussian, in which the\nkinetic isotope effect of a bimolecular reaction is analyzed:

\n\n
>>> eyring(17.26 * constants.kcal)\narray([1.38])\n>>> eyring(18.86 * constants.kcal)\narray([0.093])\n
\n\n

It is well known that, at room temperature, if you \"decrease\" a reaction\nbarrier by 1.4 kcal/mol, the reaction becomes around ten times faster:

\n\n
>>> dG = np.random.uniform(1.0, 100.0) * constants.kcal\n>>> eyring(dG - 1.4 * constants.kcal) / eyring(dG)\narray([10.])\n
\n\n

A similar relationship is found for a twofold increase in speed and a\n0.4 kcal/mol decrease in the reaction barrier (again, at room\ntemperature):

\n\n
>>> eyring(dG - 0.4 * constants.kcal) / eyring(dG)\narray([2.0])\n
\n", "signature": "(\n delta_freeenergy: Union[float, numpy.ndarray],\n molecularity: Optional[int] = None,\n temperature: Union[float, numpy.ndarray] = 298.15,\n pressure: float = 101325.0,\n volume: Optional[float] = None\n)", "funcdef": "def"}, {"fullname": "overreact.simulate", "modulename": "overreact.simulate", "type": "module", "doc": "

Module dedicated to the time simulation of reaction models.

\n\n

Here are functions that calculate reaction rates as well, which is needed for\nthe time simulations.

\n"}, {"fullname": "overreact.simulate.get_y", "modulename": "overreact.simulate", "qualname": "get_y", "type": "function", "doc": "

Simulate a reaction scheme from its rate function.

\n\n

This function provides two functions that calculate the concentrations and\nthe rates of formation at any point in time for any compound. It does that\nby solving an initial value problem (IVP) through scipy's solve_ivp\nunder the hood.

\n\n
Parameters
\n\n
    \n
  • dydt (callable):\nRight-hand side of the system.
  • \n
  • y0 (array-like):\nInitial state.
  • \n
  • t_span (array-like, optional):\nInterval of integration (t0, tf). The solver starts with t=t0 and\nintegrates until it reaches t=tf. If not given, a conservative value\nis chosen based on the system at hand (the method of choice works for\nany zeroth-, first- or second-order reactions).
  • \n
  • method (str, optional):\nIntegration method to use. See scipy.integrate.solve_ivp for details.\nKinetics problems are very often stiff and, as such, \"RK45\" is\nnormally unsuited. \"Radau\", \"BDF\" or \"LSODA\" are good choices.
  • \n
  • rtol, atol (array-like):\nSee scipy.integrate.solve_ivp for details.
  • \n
  • max_time (float, optional):\nIf t_span is not given, an interval will be estimated, but it can't\nbe larger than this parameter.
  • \n
\n\n
Returns
\n\n
    \n
  • y, r (callable):\nConcentrations and reaction rates as functions of time. The y object\nis an OdeSolution and stores attributes t_min and t_max.
  • \n
\n\n
Examples
\n\n
>>> import numpy as np\n>>> import overreact as rx\n
\n\n

A toy simulation can be performed in just two lines:

\n\n
>>> scheme = rx.parse_reactions("A <=> B")\n>>> y, r = get_y(get_dydt(scheme, np.array([1, 1])), y0=[1, 0])\n
\n\n

The y object stores information about the simulation time, which can be\nused to produce a suitable vector of timepoints for, e.g., plotting:

\n\n
>>> y.t_min, y.t_max  # doctest: +SKIP\n(0.0, 3.0)\n>>> t = np.linspace(y.t_min, y.t_max)\n>>> t  # doctest: +SKIP\narray([0. , 0.06122449, ..., 2.93877551, 3. ])\n
\n\n

Both y and r can be used to check concentrations and rates in any\npoint in time. In particular, both are vectorized:

\n\n
>>> y(t)  # doctest: +SKIP\narray([[1. , 0.94237559, ..., 0.5012394, 0.5 ],\n       [0. , 0.05762441, ..., 0.4987606, 0.5 ]])\n>>> r(t)  # doctest: +SKIP\narray([[-1.00000000e+00, ..., -1.39544265e-10],\n       [ 1.00000000e+00, ...,  1.39544265e-10]])\n
\n", "signature": "(\n dydt,\n y0,\n t_span=None,\n method='Radau',\n rtol=1e-05,\n atol=1e-11,\n max_time=86400\n)", "funcdef": "def"}, {"fullname": "overreact.simulate.get_dydt", "modulename": "overreact.simulate", "qualname": "get_dydt", "type": "function", "doc": "

Generate a rate function that models a reaction scheme.

\n\n
Parameters
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.\nMostly likely, this comes from a parsed model input file.\nSee overreact.io.parse_model.
  • \n
  • k (array-like):\nReaction rate constant(s). Units match the concentration units given to\nthe returned function dydt.
  • \n
  • ef (float, optional):\nEquilibrium factor. This is a parameter that can be used to scale the\nreaction rates associated to half-equilibrium reactions such that they\nare faster than the other reactions.
  • \n
\n\n
Returns
\n\n
    \n
  • dydt (callable):\nReaction rate function. The actual reaction rate constants employed\nare stored in the attribute k of the returned function. If JAX is\navailable, the attribute jac will hold the Jacobian function of\ndydt.
  • \n
\n\n
Notes
\n\n

The returned function is suited to be used by ODE solvers such as\nscipy.integrate.solve_ivp or the older scipy.integrate.ode (see\nexamples below). This is actually what the function get_y from the\ncurrent module does.

\n\n
Examples
\n\n
>>> import numpy as np\n>>> import overreact as rx\n
\n\n
>>> scheme = rx.parse_reactions("A <=> B")\n>>> dydt = get_dydt(scheme, np.array([1, 1]))\n>>> dydt(0.0, np.array([1., 1.]))  # doctest: +SKIP\narray([0., 0.])\n
\n\n

If available, JAX is used for JIT compilation. This will make dydt\ncomplain if given lists instead of numpy arrays. So stick to the safer,\nfaster side as above.

\n\n

The actually used reaction rate constants can be inspected with the k\nattribute of dydt:

\n\n
>>> dydt.k  # doctest: +SKIP\narray([1., 1.])\n
\n\n

If JAX is available, the Jacobian function will be available as\ndydt.jac:

\n\n
>>> dydt.jac(0.0, np.array([1., 1.]))  # doctest: +SKIP\nDeviceArray([[-1.,  1.],\n             [ 1., -1.]], dtype=float64)\n
\n", "signature": "(scheme, k, ef=5)", "funcdef": "def"}, {"fullname": "overreact.simulate.get_fixed_scheme", "modulename": "overreact.simulate", "qualname": "get_fixed_scheme", "type": "function", "doc": "

Generate an alternative scheme with some concentrations fixed.

\n\n

This function returns data that allow the microkinetic simulation of a\nreaction network under constraints, namely when some compounds have fixed\nconcentrations. This works by 1. removing all references to the fixed\ncompounds and by 2. properly multiplying the reaction rate constants by\nthe respective concentrations.

\n\n
Parameters
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.\nMostly likely, this comes from a parsed model input file.\nSee overreact.io.parse_model.
  • \n
  • k (array-like):\nReaction rate constant(s). Units match the concentration units given to\nthe returned function dydt.
  • \n
  • fixed_y0 (dict-like):\nFixed initial state. Units match the concentration units given to\nthe returned function dydt.
  • \n
\n\n
Returns
\n\n
    \n
  • scheme (Scheme):\nAssociated reaction scheme with all references to fixed compounds\nremoved.
  • \n
  • k (array-like):\nAssociated (effective) reaction rate constants that model the fixed\nconcentrations.
  • \n
\n\n
Notes
\n\n

Keep in mind that when a compound get its concentration fixed, the\nreaction scheme no longer conserves matter. You can think of it as\nreacting close to an infinite source of the compound, but it accumulates\nin the milleu at the given concentration.

\n\n
Examples
\n\n
>>> import numpy as np\n>>> import overreact as rx\n
\n\n

Equilibria under a specific pH can be easily modeled:

\n\n
>>> pH = 7\n>>> scheme = rx.parse_reactions("AH <=> A- + H+")\n>>> k = np.array([1, 1])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H+": 10**-pH})\n>>> scheme\nScheme(compounds=('AH', 'A-'),\n       reactions=('AH -> A-',\n                  'A- -> AH'),\n       is_half_equilibrium=(True, True),\n       A=((-1.0, 1.0),\n          (1.0, -1.0)),\n       B=((-1.0, 0.0),\n          (1.0, 0.0)))\n>>> k\narray([1.e+00, 1.e-07])\n
\n\n

It is also possible to model the fixed activity of a solvent, for\ninstance:

\n\n
>>> scheme = rx.parse_reactions("A + 2H2O -> B")\n>>> k = np.array([1.0])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H2O": 55.6})\n>>> scheme\nScheme(compounds=('A', 'B'),\n       reactions=('A -> B',),\n       is_half_equilibrium=(False,),\n       A=((-1.0,),\n          (1.0,)),\n       B=((-1.0,),\n          (1.0,)))\n>>> k\narray([3091.36])\n
\n\n

Multiple reactions work fine, see both examples below:

\n\n
>>> pH = 12\n>>> scheme = rx.parse_reactions("B <- AH <=> A- + H+")\n>>> k = np.array([10.0, 1, 1])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H+": 10**-pH})\n>>> scheme\nScheme(compounds=('AH', 'B', 'A-'),\n       reactions=('AH -> B',\n                  'AH -> A-',\n                  'A- -> AH'),\n       is_half_equilibrium=(False, True, True),\n       A=((-1.0, -1.0, 1.0),\n          (1.0, 0.0, 0.0),\n          (0.0, 1.0, -1.0)),\n       B=((-1.0, -1.0, 0.0),\n          (1.0, 0.0, 0.0),\n          (0.0, 1.0, 0.0)))\n>>> k\narray([1.e+01, 1.e+00, 1.e-12])\n
\n\n
>>> pH = 2\n>>> scheme = rx.parse_reactions(["AH <=> A- + H+", "B- + H+ <=> BH"])\n>>> k = np.array([1, 1, 2, 2])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H+": 10**-pH})\n>>> scheme\nScheme(compounds=('AH', 'A-', 'B-', 'BH'),\n       reactions=('AH -> A-',\n                  'A- -> AH',\n                  'B- -> BH',\n                  'BH -> B-'),\n       is_half_equilibrium=(True, True, True, True),\n       A=((-1.0, 1.0, 0.0, 0.0),\n          (1.0, -1.0, 0.0, 0.0),\n          (0.0, 0.0, -1.0, 1.0),\n          (0.0, 0.0, 1.0, -1.0)),\n       B=((-1.0, 0.0, 0.0, 0.0),\n          (1.0, 0.0, 0.0, 0.0),\n          (0.0, 0.0, -1.0, 0.0),\n          (0.0, 0.0, 1.0, 0.0)))\n>>> k\narray([1. , 0.01, 0.02, 2. ])\n
\n\n

Multiple fixed compounds also work fine:

\n\n
>>> pH = 6\n>>> scheme = rx.parse_reactions("A + H2O -> B <=> B- + H+")\n>>> k = np.array([1.0, 100.0, 2.0])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H+": 10**-pH, "H2O": 55.6})\n>>> scheme\nScheme(compounds=('A', 'B', 'B-'),\n       reactions=('A -> B',\n                  'B -> B-',\n                  'B- -> B'),\n       is_half_equilibrium=(False, True, True),\n       A=((-1.0, 0.0, 0.0),\n          (1.0, -1.0, 1.0),\n          (0.0, 1.0, -1.0)),\n       B=((-1.0, 0.0, 0.0),\n          (1.0, -1.0, 0.0),\n          (0.0, 1.0, 0.0)))\n>>> k\narray([5.56e+01, 1.00e+02, 2.00e-06])\n
\n\n

This function is a no-op if fixed_y0 is empty, which is very important\nfor overall code consistency:

\n\n
>>> scheme = rx.parse_reactions(["AH <=> A- + H+", "B- + H+ <=> BH"])\n>>> k = np.array([1, 1, 2, 2])\n>>> new_scheme, new_k = rx.get_fixed_scheme(scheme, k, {})\n>>> new_scheme == scheme\nTrue\n>>> np.allclose(new_k, k)\nTrue\n
\n", "signature": "(scheme, k, fixed_y0)", "funcdef": "def"}, {"fullname": "overreact.thermo", "modulename": "overreact.thermo", "type": "module", "doc": "

Module dedicated to the calculation of thermodynamic properties.

\n"}, {"fullname": "overreact.thermo.equilibrium_constant", "modulename": "overreact.thermo", "qualname": "equilibrium_constant", "type": "function", "doc": "

Calculate an equilibrium constant from a reaction Gibbs free energy.

\n\n

This function uses the usual relationship between reaction Gibbs energy\nand equilibrium constant\n:

\n\n

$$K(T) = \\exp\\left(-\\frac{\\Delta_\\text{r} G^\\circ}{R T}\\right)$$

\n\n

If delta_moles is given, the above will be multiplied by a term\n\\( \\left( \\frac{R T}{p} \\right)^{-\\Delta n} \\), which effectively\ntransforms a \\( K_p \\) equilibrium constant into a \\( K_c \\)\n(see below).

\n\n
Parameters
\n\n
    \n
  • delta_freeenergy (array-like):\nDelta Gibbs reaction free energies. This assumes values were already\ncorrected for a one molar reference state.
  • \n
  • delta_moles (array-like, optional):\nDifference in moles between products and reactants. If set, this\nmultiplies the end result by\n\\( \\left( \\frac{R T}{p} \\right)^{-\\Delta n} \\), which effectively\ncalculates a solution equilibrium constant for gas phase data. You\nshould set this to None if your free energies were already adjusted\nfor solution Gibbs free energies.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
  • volume (float, optional):\nMolar volume. This substitutes \\( \\frac{R T}{p} \\) if given. See\ndelta_moles.
  • \n
\n\n
Returns
\n\n
    \n
  • K (array-like):\nEquilibrium constant.
  • \n
\n\n
Notes
\n\n

If you want to calculate a solution equilibrium constant from gas phase data, set\ndelta_moles to the difference in moles between products and reactants.\nAlternatively, convert your energies to solution Gibbs free energies and\nset delta_moles to None.

\n\n
Examples
\n\n

The following is an example from the\nLibreTexts Chemistry Library.\nConsider the following equilibrium:

\n\n

$$\\ce{2 SO2(g) + O2(g) <=> 2 SO3(g)}$$

\n\n

with concentrations \\( c_{\\ce{SO2(g)}} = 0.2 M \\),\n\\( c_{\\ce{O2(g)}} = 0.5 M \\) and \\( c_{\\ce{SO3(g)}} = 0.7 M \\) (room\ntemperature). Its \\( K_c \\) is given by:

\n\n
>>> Kc = 0.7**2 / (0.2**2 * 0.5)\n>>> Kc\n24.5\n
\n\n

You could use equilibrium_constant to reach the same result using the\nGibbs reaction free energy (which can easily be obtained from\n\\( K_c \\)):

\n\n
>>> temperature = 298.15\n>>> dG = -constants.R * temperature * np.log(Kc)\n>>> equilibrium_constant(dG)\narray([24.5])\n
\n\n

By giving a delta_moles value (in this case, \\( 2 - 2 - 1 = -1 \\)),\nwe can calculate the corresponding K_p:

\n\n
>>> equilibrium_constant(dG, delta_moles=-1)\narray([1.002])\n
\n\n

(As expected, it makes sense for gases to favor the most entropic side of\nthe equilibrium.) The example above clearly used \"solution-based\" data\n(our \\( K_c \\) was calculated using molar quantities, which means\nreference volumes of one liter). You could convert it to gas phase data\nto get the same result, by changing the reference state (in this case,\nfrom one molar to one atmosphere using change_reference_state):

\n\n
>>> dG += temperature * rx.change_reference_state()\n>>> equilibrium_constant(dG)\narray([1.002])\n
\n\n

Having gas phase information, the inverse path can be taken just by\ninverting the sign of delta_moles:

\n\n
>>> equilibrium_constant(dG, delta_moles=1)\narray([24.5])\n
\n\n

The following example is from\nWikipedia.\nThe reactions are two copper complex forming equilibria with two\ndifferent ligands. Since this reaction takes place in solution, it is the\nsolution standard Gibbs reaction free energy that is given:

\n\n
>>> dG1 = -37.4e3\n>>> np.log10(equilibrium_constant(dG1))\narray([6.55])\n>>> dG2 = -60.67e3\n>>> np.log10(equilibrium_constant(dG2))\narray([10.62])\n
\n\n

The above are thus \\( \\log_{10}(K_c) \\). Since we are talking about a\nmono- and a bidendate ligands, the delta_moles are -4 and -2,\nrespectively, and we could obtain the \\( \\log_{10}(K_p) \\) the following\nway:

\n\n
>>> np.log10(equilibrium_constant(dG1, delta_moles=-4))\narray([0.998])\n>>> np.log10(equilibrium_constant(dG2, delta_moles=-2))\narray([7.85])\n
\n\n

You can easily check that the above values match the values given\nhere.

\n", "signature": "(\n delta_freeenergy: Union[float, numpy.ndarray],\n delta_moles: Union[int, numpy.ndarray, NoneType] = None,\n temperature: Union[float, numpy.ndarray] = 298.15,\n pressure: float = 101325.0,\n volume: Optional[float] = None\n)", "funcdef": "def"}, {"fullname": "overreact.thermo.change_reference_state", "modulename": "overreact.thermo", "qualname": "change_reference_state", "type": "function", "doc": "

Calculate an additive entropy correction to a change in reference states.

\n\n

$$\\Delta G_\\text{corr} =\n R T \\ln \\left( \\frac{\\chi_\\text{new}}{\\chi_\\text{old}} \\right)$$

\n\n

The value returned can be directly multiplied by temperature and summed to\nthe old reference free energies to obtain free energies with respect to a\nnew reference. See notes below.

\n\n

For instance, the concentration correction to Gibbs free energy for a\ngas-to-liquid standard state change is simply\n(\\( c^\\circ = \\frac{\\text{1 atm}}{R T} \\)),

\n\n

$$\\Delta G_\\text{conc} =\n R T \\ln \\left( \\frac{\\text{1 M}}{c^\\circ} \\right)$$

\n\n
Parameters
\n\n
    \n
  • new_reference (array-like, optional):\nNew reference state. Default value corresponds to 1 mol/liter.
  • \n
  • old_reference (array-like, optional):\nOld reference state. Default value corresponds to the concentration of\nan ideal gas at the given temperature and 1 atm.
  • \n
  • sign (float, optional):\nSign of the change in reference state. Default value is 1. This only\nmultiplies the final result.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
  • volume (float, optional):\nMolar volume.
  • \n
\n\n
Returns
\n\n
    \n
  • correction (array-like):\nEntropy correction in J/mol\u00b7K.
  • \n
\n\n
Notes
\n\n

This function can be used to add any entropy correction in the form above.\nThe only drawback is that, sometimes, those corrections are written with a\nminus sign in front of them (this implies switching the roles of\nold_reference and new_reference). The easiest way to accomplish this is\nby using sign=-1 or multiplying the result by -1.

\n\n
Examples
\n\n

By default, the correction returns a change in concentration from the gas\nphase standard concentration to the solvated-state standard concentration:

\n\n
>>> -rx.change_reference_state() / constants.calorie\n-6.4\n>>> 298.15 * rx.change_reference_state() / constants.kcal\n1.89\n>>> 273.15 * rx.change_reference_state(temperature=273.15) / constants.kcal\n1.69\n
\n\n

But this function can also be used to adjust symmetry effects from C1\ncalculations (symmetry number equals to one). For D7h, for instance, the\nsymmetry number is 14:

\n\n
>>> -298.15 * rx.change_reference_state(14, 1) / constants.kcal\n-1.56\n
\n\n
>>> rx.change_reference_state(sign=-1) == -rx.change_reference_state()\nTrue\n
\n", "signature": "(\n new_reference: float = 1000.0,\n old_reference: Optional[float] = None,\n sign: int = 1,\n temperature: Union[float, numpy.ndarray] = 298.15,\n pressure: float = 101325.0,\n volume: Optional[float] = None\n)", "funcdef": "def"}, {"fullname": "overreact.tunnel", "modulename": "overreact.tunnel", "type": "module", "doc": "

Module dedicated to quantum tunneling approximations.

\n"}, {"fullname": "overreact.tunnel.eckart", "modulename": "overreact.tunnel", "qualname": "eckart", "type": "function", "doc": "

Calculate the Eckart correction to quantum tunneling.

\n\n

References are\nJ. Phys. Chem. 1962, 66, 3, 532\u2013533\nand\nJ. Res. Natl. Inst. Stand. Technol., 1981, 86, 357.

\n\n
Parameters
\n\n
    \n
  • vibfreq (array-like):\nMagnitude of the imaginary frequency in cm$^{-1}$. Only the absolute value\nis used.
  • \n
  • delta_forward (array-like):\nActivation enthalpy at 0 K for the forward reaction.
  • \n
  • delta_backward (array-like, optional):\nActivation enthalpy at 0 K for the reverse reaction. If delta_backward\nis not given, the \"symmetrical\" Eckart model is used (i.e.,\ndelta_backward == delta_forward is assumed).
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • kappa (array-like):\nThe quantum tunneling correction.
  • \n
\n\n
Raises
\n\n
    \n
  • ValueError: If vibfreq is zero.
  • \n
\n\n
Examples
\n\n
>>> eckart(1218, 13672.624, 24527.729644, temperature=300)\narray(3.9)\n>>> eckart(1218, 13672.624, 24527.729644, temperature=[200, 298.15])\narray([17.1, 4.0])\n>>> eckart([1218, 200], 13672.624, 24527.729644, temperature=400)\narray([2.3, 1.0])\n
\n\n

If no backward barrier is given, a symmetric Eckart potential is assumed:

\n\n
>>> eckart(414.45, 394.54)\narray(1.16)\n>>> eckart(414.45, 789.08)\narray(1.3)\n>>> eckart(3315.6, 3156.31)\narray(3.3)\n
\n", "signature": "(\n vibfreq: float,\n delta_forward: float,\n delta_backward: Optional[float] = None,\n temperature: Union[float, numpy.ndarray] = 298.15\n) -> Union[float, numpy.ndarray]", "funcdef": "def"}, {"fullname": "overreact.tunnel.wigner", "modulename": "overreact.tunnel", "qualname": "wigner", "type": "function", "doc": "

Calculate the Wigner correction to quantum tunneling.

\n\n
Parameters
\n\n
    \n
  • vibfreq (array-like):\nMagnitude of the imaginary frequency in cm$^{-1}$. Only the absolute value\nis used.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • kappa (array-like):\nThe quantum tunneling correction.
  • \n
\n\n
Raises
\n\n
    \n
  • ValueError: If vibfreq is zero.
  • \n
\n\n
Examples
\n\n
>>> wigner(1821.0777)\n4.218\n>>> wigner(262.38)\n1.06680\n>>> wigner(113.87)\n1.01258\n>>> wigner(169.14)\n1.02776\n
\n", "signature": "(\n vibfreq: float,\n temperature: Union[float, numpy.ndarray] = 298.15\n) -> float", "funcdef": "def"}]; + /** pdoc search index */const docs = [{"fullname": "overreact", "modulename": "overreact", "type": "module", "doc": "
\n\n

\n\n

\n\n

\n\n

\n\n

\n\n
\"overreact\"\nsrc=\"https://raw.githubusercontent.com/geem-lab/overreact-guide/master/logo.png\"\n/
\n\n
\n\n

overreact is a library and a command-line tool for building and\nanalyzing homogeneous microkinetic models from first-principles\ncalculations:

\n\n
In [1]: from overreact import api\n\nIn [2]: api.get_k("S -> E\u2021 -> S",\n   ...:           {"S": "data/ethane/B97-3c/staggered.out",\n   ...:            "E\u2021": "data/ethane/B97-3c/eclipsed.out"})\nOut[2]: array([8.16880917e+10])\n
\n\n\n\n

\n \n \ud83e\udd14 What is microkinetic modeling?\n \n

\n Microkinetic modeling is a technique used to predict the outcome\n of complex chemical reactions.\n It can be used\n to investigate the catalytic transformations\n of molecules.\n overreact makes it easy to create\n and analyze microkinetic models built\n from computational chemistry data.\n

\n

\n\n


\n\n

\n \n \ud83e\uddd0 What do you mean by first-principles calculations?\n \n

\n We use the term first-principles calculations to refer to\n calculations performed using quantum chemical modern methods such as\n Wavefunction\n and\n Density Functional\n theories.\n For instance, the three-line example code above calculates the rate of methyl rotation in ethane (at\n B97-3c).\n (Rather surprisingly, the error found is less than 2%\n when compared to available experimental results.)\n

\n

\n\n


\n\n

overreact uses precise thermochemical partition funtions, tunneling\ncorrections and data is parsed directly from computational chemistry\noutput files thanks to cclib (see the\nlist of its supported programs).

\n\n

Installation

\n\n

overreact is a Python package, so you can easily install it with\npip:

\n\n
$ pip install "overreact[cli,fast]"\n
\n\n

See the\ninstallation guide\nfor more details.

\n\n
\n

\ud83d\ude80 Where to go from here? Take a look at the\n short introduction.\n Or see\n below\n for more guidance.

\n
\n\n

Citing overreact

\n\n

If you use overreact in your research, please cite:

\n\n
\n

F. S. S. Schneider and G. F. Caramori. _geem-lab/overreact: a tool for\n creating and analyzing microkinetic models built from computational chemistry\n data, v1.0.2_. 2021.\n DOI:10.5281/zenodo.5730603.\n Freely available at: <https://github.com/geem-lab/overreact>.

\n
\n\n

Here's the reference in BibTeX format:

\n\n
@misc{overreact2021,\n  howpublished = {\\url{https://github.com/geem-lab/overreact}}\n  year = {2021},\n  author = {Schneider, F. S. S. and Caramori, G. F.},\n  title = {\n    \\textbf{geem-lab/overreact}: a tool for creating and analyzing\n    microkinetic models built from computational chemistry data, v1.0.2\n  },\n  doi = {10.5281/zenodo.5730603},\n  url = {https://zenodo.org/record/5730603},\n  publisher = {Zenodo},\n  copyright = {Open Access}\n}\n
\n\n
\n

\u270f\ufe0f A paper describing overreact is currently being prepared. When it\n is published, the above BibTeX entry will be updated.

\n
\n\n

License

\n\n

overreact is open-source, released under the permissive MIT license. See\nthe LICENSE agreement.

\n\n

Funding

\n\n

This project was developed at the GEEM lab\n(Federal University of Santa Catarina, Brazil), and was\npartially funded by the\nBrazilian National Council for Scientific and Technological Development (CNPq),\ngrant number 140485/2017-1.

\n"}, {"fullname": "overreact.api", "modulename": "overreact.api", "type": "module", "doc": "

This module contains the high-level application programming interface.

\n\n

If you intend to use overreact as a library in a project, you should\nprobably start here.

\n"}, {"fullname": "overreact.api.get_k", "modulename": "overreact.api", "qualname": "get_k", "type": "function", "doc": "

Obtain reaction rate constants for a given reaction scheme.

\n\n
Parameters
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • compounds (dict-like, optional):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • bias (array-like, optional):\nEnergy to be added to free energies.
  • \n
  • tunneling (str or None, optional):\nChoose between \"eckart\", \"wigner\" or None (or \"none\").
  • \n
  • qrrho (bool or tuple-like, optional):\nApply both the quasi-rigid rotor harmonic oscillator (QRRHO)\napproximations of M. Head-Gordonand others (enthalpy correction, see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\nand S. Grimme (entropy correction, see\nTheory. Chem. Eur. J., 2012, 18: 9955-9964)\non top of the classical RRHO.
  • \n
  • scale (str, optional):\nReaction rate units. Possible values are \"cm3 mol-1 s-1\",\n\"l mol-1 s-1\", \"m3 mol-1 s-1\", \"cm3 particle-1 s-1\", \"mmHg-1 s-1\" and\n\"atm-1 s-1\".
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
  • delta_freeenergies (array-like, optional):\nUse this instead of obtaining delta free energies from the compounds.
  • \n
  • molecularity (array-like, optional):\nReaction order, i.e., number of molecules that come together to react.\nIf set, this is used to calculate delta_moles for\noverreact.thermo.equilibrium_constant, which effectively calculates a solution\nequilibrium constant between reactants and the transition state for\ngas phase data. You should set this to None if your free energies\nwere already adjusted for solution Gibbs free energies.
  • \n
  • volume (float, optional):\nMolar volume.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Notes
\n\n

Some symbols are accepted as alternatives in \"scale\": \"M-1\", \"ml\" and\n\"torr-1\" are understood as \"l mol-1\", \"cm3\" and \"mmHg-1\", respectively.

\n\n
Examples
\n\n

Below is an example of an estimate for the rate of methyl rotation in\nethane (a trivial attempt to reproduce\nScience, 2006, 313, 5795, 1951-1955).\nHow many turns it does per second?

\n\n
>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> get_k(model.scheme, model.compounds)\narray([8.16e+10])\n>>> get_k(model.scheme, model.compounds, qrrho=(False, True))\narray([8.24968117e+10])\n>>> get_k(model.scheme, model.compounds, qrrho=False)\narray([8.26909266e+10])\n>>> get_k(model.scheme, model.compounds, tunneling="wigner")\narray([7.99e+10])\n>>> get_k(model.scheme, model.compounds, tunneling=None)\narray([7.35e+10])\n
\n\n

The calculated value is off by less than 2% from the experimental value\n(\\( \\frac{1}{12 \\times 10^{-12}} \\text{s}^{-1} = 8.33 \\times 10^{10} \\text{s}^{-1} \\)).\nWe use Eckart tunneling by default, but see the effect of changing it\nabove.

\n\n

The units of the returned reaction rate constants can be selected for\nnon-unimolecular processes. The following is an attempt to reproduce\nJ Atmos Chem, 1996 23, 37\u201349 for\nthe reaction of proton-withdrawal by a chloride radical from the methane\nmolecule\n\\( \\ce{CH4 + \\cdot Cl -> [H3C\\cdots H\\cdots Cl]^\\ddagger -> H3C\\cdot + HCl} \\):

\n\n
>>> model = rx.parse_model("data/tanaka1996/UMP2/cc-pVTZ/model.jk")\n>>> get_k(model.scheme, model.compounds, temperature=300,\n...       scale="cm3 particle-1 s-1")\narray([9.60e-14])\n
\n\n

(By the way, according to the Jet Propulsion Laboratory,\nPublication No. 19-5,\nthe experimental reaction rate constant for this reaction is\n\\( 1.0 \\times 10^{-13} \\text{cm}^3 \\text{particle}^{-1} \\text{s}^{-1} \\).)

\n\n

The returned units are \"M-1 s-1\" by default:

\n\n
>>> get_k(model.scheme, model.compounds) \\\n... == get_k(model.scheme, model.compounds, scale="l mol-1 s-1")\narray([ True])\n
\n\n

You can also turn the tunneling correction off by using the string \"none\":

\n\n
>>> get_k(model.scheme, model.compounds, tunneling="none") \\\n... == get_k(model.scheme, model.compounds, tunneling=None)\narray([ True])\n
\n\n

You can set a simple energy bias, either as a constant or compound-wise:

\n\n
>>> get_k(model.scheme, model.compounds, bias=1.0 * constants.kcal,\n...       temperature=300.0, scale="cm3 particle-1 s-1")\narray([5.14e-13])\n>>> get_k(model.scheme, model.compounds,\n...       bias=np.array([0.0, 0.0, -1.4, 0.0, 0.0]) * constants.kcal,\n...       temperature=300.0, scale="cm3 particle-1 s-1")\narray([1.1e-12])\n
\n", "signature": "(\n scheme: overreact.core.Scheme,\n compounds: Optional[dict] = None,\n bias: float = 0.0,\n tunneling: str = 'eckart',\n qrrho: Union[bool, tuple[bool, bool]] = True,\n scale: str = 'l mol-1 s-1',\n temperature: float = 298.15,\n pressure: float = 101325.0,\n delta_freeenergies: Optional[float] = None,\n molecularity: Optional[float] = None,\n volume: Optional[float] = None\n) -> float", "funcdef": "def"}, {"fullname": "overreact.api.get_kappa", "modulename": "overreact.api", "qualname": "get_kappa", "type": "function", "doc": "

Obtain tunneling transmission coefficients at a given temperature.

\n\n

One tunneling transmission coefficient is calculated for each reaction. If\na reaction lacks a transition state (i.e., a half-equilibrium reaction),\nits transmission coefficient is set to unity.

\n\n
Parameters
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • method (str or None, optional):\nChoose between \"eckart\", \"wigner\" or None (or \"none\").
  • \n
  • qrrho (bool, optional):\nApply both the quasi-rigid rotor harmonic oscillator (QRRHO)\napproximations of M. Head-Gordon and others (enthalpy correction, see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\nand S. Grimme (entropy correction, see\nTheory. Chem. Eur. J., 2012, 18: 9955-9964)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Raises
\n\n
    \n
  • ValueError: If method is not supported.
  • \n
\n\n
Examples
\n\n

Below is an example of an estimate of how much quantum tunneling\ncontributes to the rate of methyl rotation in ethane (see\nScience, 2006, 313, 5795, 1951-1955\nfor some interesting experimental data on this reaction).

\n\n
>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> kappa = get_kappa(model.scheme, model.compounds)\n>>> kappa\narray([1.110])\n>>> get_kappa(model.scheme, model.compounds, method="none")\narray([1.0])\n>>> get_kappa(model.scheme, model.compounds, method="none") \\\n... == get_kappa(model.scheme, model.compounds, method=None)\narray([ True])\n
\n\n

You can calculate each piece of the reaction rate constant by hand,\nif you want. Just make sure that you don't calculate the tunneling\ncoefficient twice:

\n\n
>>> kappa * get_k(model.scheme, model.compounds, tunneling=None)\narray([8.e+10])\n
\n", "signature": "(\n scheme: overreact.core.Scheme,\n compounds: dict,\n method: str = 'eckart',\n qrrho: bool = True,\n temperature: float = 298.15\n)", "funcdef": "def"}, {"fullname": "overreact.api.get_freeenergies", "modulename": "overreact.api", "qualname": "get_freeenergies", "type": "function", "doc": "

Obtain free energies for compounds at a given temperature and pressure.

\n\n
Parameters
\n\n
    \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • bias (array-like, optional):\nEnergy to be added to free energies.
  • \n
  • environment (str or None, optional):\nChoose between \"gas\" and a solvent. This is chosen for you by default,\nbased on the names of each compound. If given, all compounds will\nhave the same behavior.
  • \n
  • method (str, optional):\nThis is a placeholder for future functionality.\nThere are plans to implement more sophisticated methods for calculating\nentropies such as in\nPhys. Chem. Chem. Phys., 2019, 21, 18920-18929\nand\nJ. Chem. Theory Comput. 2019, 15, 5, 3204\u20133214.\nHead over to the\ndiscussions if\nyou're interested and would like to contribute.\nLeave this as \"standard\" for now.
  • \n
  • qrrho (bool or tuple-like, optional):\nApply both the quasi-rigid rotor harmonic oscillator (QRRHO)\napproximations of M. Head-Gordon and others (enthalpy correction, see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\nand S. Grimme (entropy correction, see\nTheory. Chem. Eur. J., 2012, 18: 9955-9964)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Examples
\n\n
>>> import overreact as rx\n>>> from overreact import _constants as constants\n>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> freeenergies = get_freeenergies(model.compounds, qrrho=(False, True))\n>>> (freeenergies - freeenergies.min()) / constants.kcal\narray([0. , 2.62281461])\n>>> freeenergies = get_freeenergies(model.compounds)\n>>> (freeenergies - freeenergies.min()) / constants.kcal\narray([0. , 2.62862818])\n
\n\n

You can consider all compounds as solvated if you want:

\n\n
>>> sol_freeenergies = get_freeenergies(model.compounds, environment="solvent")\n>>> (sol_freeenergies - freeenergies) / constants.kcal\narray([1.89432845, 1.89432845])\n
\n\n

You can set a simple energy bias, either as a constant or compound-wise:

\n\n
>>> get_freeenergies(model.compounds, bias=1.0) - freeenergies\narray([1., 1.])\n>>> get_freeenergies(model.compounds, bias=-1.0) - freeenergies\narray([-1., -1.])\n>>> get_freeenergies(model.compounds, bias=[1.0, -1.0]) - freeenergies\narray([ 1., -1.])\n
\n", "signature": "(\n compounds: dict,\n bias: float = 0.0,\n environment: Optional[str] = None,\n method: str = 'standard',\n qrrho: Union[bool, tuple[bool, bool]] = True,\n temperature: float = 298.15,\n pressure: float = 101325.0\n)", "funcdef": "def"}, {"fullname": "overreact.api.get_entropies", "modulename": "overreact.api", "qualname": "get_entropies", "type": "function", "doc": "

Obtain entropies for compounds at a given temperature and pressure.

\n\n
Parameters
\n\n
    \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • environment (str or None, optional):\nChoose between \"gas\" and a solvent. This is chosen for you by default,\nbased on the names of each compound (e.g. A(g) or A is gas,\nA(w) or A(...) is solvated). In case this is given, all compounds\nwill have the same behavior.
  • \n
  • method (str, optional):\nThis is a placeholder for future functionality.\nThere are plans to implement more sophisticated methods for calculating\nentropies such as in\nPhys. Chem. Chem. Phys., 2019, 21, 18920-18929\nand\nJ. Chem. Theory Comput. 2019, 15, 5, 3204\u20133214.\nHead over to the\ndiscussions if\nyou're interested and would like to contribute.\nLeave this as \"standard\" for now.
  • \n
  • qrrho (bool, optional):\nApply the quasi-rigid rotor harmonic oscillator (QRRHO) approximation of\nS. Grimme (see\nTheory. Chem. Eur. J., 2012, 18: 9955-9964)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Examples
\n\n
>>> import overreact as rx\n>>> from overreact import _constants as constants\n>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> entropies = get_entropies(model.compounds)\n>>> (entropies - entropies.min()) / constants.calorie\narray([1.4, 0. ])\n
\n\n

You can consider all compounds as solvated if you want:

\n\n
>>> sol_entropies = get_entropies(model.compounds, environment="solvent")\n>>> (sol_entropies - entropies) / constants.calorie\narray([-6.35360874, -6.35360874])\n
\n", "signature": "(\n compounds: dict,\n environment: Optional[str] = None,\n method: str = 'standard',\n qrrho: bool = True,\n temperature: float = 298.15,\n pressure: float = 101325.0\n)", "funcdef": "def"}, {"fullname": "overreact.api.get_enthalpies", "modulename": "overreact.api", "qualname": "get_enthalpies", "type": "function", "doc": "

Obtain enthalpies for compounds at a given temperature.

\n\n
Parameters
\n\n
    \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • qrrho (bool, optional):\nApply the quasi-rigid rotor harmonic oscillator (QRRHO) approximation of\nM. Head-Gordon and others (see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Examples
\n\n
>>> import overreact as rx\n>>> from overreact import _constants as constants\n>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> enthalpies = get_enthalpies(model.compounds)\n>>> (enthalpies - enthalpies.min()) / constants.kcal\narray([0. , 2.20053981])\n
\n\n

The enthalpies at absolute zero can easily be obtained (this is used,\ne.g., in the calculation of the Eckart tunneling coefficient, see\noverreact.tunnel.eckart). We can use this to calculate, for instance,\nthe thermal contributions to the enthalpy:

\n\n
>>> zero_enthalpies = get_enthalpies(model.compounds, temperature=0)\n>>> (enthalpies - zero_enthalpies) / constants.kcal\narray([2.78, 2.50])\n
\n", "signature": "(compounds: dict, qrrho: bool = True, temperature: float = 298.15)", "funcdef": "def"}, {"fullname": "overreact.api.get_internal_energies", "modulename": "overreact.api", "qualname": "get_internal_energies", "type": "function", "doc": "

Obtain internal energies for compounds at a given temperature.

\n\n
Parameters
\n\n
    \n
  • compounds (dict-like):\nA descriptor of the compounds.\nMostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.
  • \n
  • qrrho (bool, optional):\nApply the quasi-rigid rotor harmonic oscillator (QRRHO) approximation of\nM. Head-Gordon and others (see\nJ. Phys. Chem. C 2015, 119, 4, 1840\u20131850)\non top of the classical RRHO.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • array-like
  • \n
\n\n
Examples
\n\n
>>> import overreact as rx\n>>> from overreact import _constants as constants\n>>> model = rx.parse_model("data/ethane/B97-3c/model.k")\n>>> internal_energies = get_internal_energies(model.compounds)\n>>> (internal_energies - internal_energies.min()) / constants.kcal\narray([0. , 2.20053981])\n
\n", "signature": "(compounds: dict, qrrho: bool = True, temperature: float = 298.15)", "funcdef": "def"}, {"fullname": "overreact.coords", "modulename": "overreact.coords", "type": "module", "doc": "

Module dedicated to classifying molecules into point groups.

\n"}, {"fullname": "overreact.coords.find_point_group", "modulename": "overreact.coords", "qualname": "find_point_group", "type": "function", "doc": "

Determine point group of structure.

\n\n
Parameters
\n\n
    \n
  • atommasses (array-like):\nAtomic masses in atomic mass units (amu).
  • \n
  • atomcoords (array-like):\nAtomic coordinates.
  • \n
  • proper_axes (sequence of tuples of int, array-like, optional):\nProper symmetry axes of rotation.
  • \n
  • rtol (float, optional):\nThe relative tolerance parameter (see numpy.isclose).
  • \n
  • atol (float, optional):\nThe absolute tolerance parameter (see numpy.isclose).
  • \n
\n\n
Returns
\n\n
    \n
  • str: Point group symbol.
  • \n
\n\n
Examples
\n\n
>>> find_point_group([1], [[0, 0, 1]])\n'K'\n>>> find_point_group([1, 1], [[0, 0, 1], [0, 0, 0]])\n'D\u221eh'\n>>> find_point_group([1.008, 35.45], [[0, 0, 1], [0, 0, 0]])\n'C\u221ev'\n>>> find_point_group([16, 12, 16], [[1, 0, 1], [1, 0, 0], [1, 0, -1]])\n'D\u221eh'\n>>> find_point_group([16, 12, 32], [[1, 1, 1], [1, 1, 0], [1, 1, -1]])\n'C\u221ev'\n>>> find_point_group([12, 12, 12, 12], [[1, 0, 0],\n...                                     [0, 1, 0],\n...                                     [0, 0, 0],\n...                                     [1, 1, 0]])\n'D4h'\n
\n", "signature": "(atommasses, atomcoords, proper_axes=None, rtol=0.0, atol=0.01)", "funcdef": "def"}, {"fullname": "overreact.coords.symmetry_number", "modulename": "overreact.coords", "qualname": "symmetry_number", "type": "function", "doc": "

Return rotational symmetry number for point group.

\n\n

This function has a set of the most common point groups precomputed, but is\nable to calculate the symmetry number if it is not found in known tables.\nMost precomputed values are from\nTheor Chem Account 2007 118, 813\u2013826.

\n\n
Parameters
\n\n
    \n
  • point_group (str):\nPoint group symbol.
  • \n
\n\n
Returns
\n\n
    \n
  • int: Rotational symmetry number.
  • \n
\n\n
Raises
\n\n
    \n
  • ValueError: If point group is not found in precomputed values.
  • \n
\n\n
Examples
\n\n
>>> symmetry_number("C4")\n4\n>>> symmetry_number("C4") == symmetry_number("C4h")\nTrue\n>>> symmetry_number("C6")\n6\n>>> symmetry_number("C6") == symmetry_number("C6v")\nTrue\n>>> symmetry_number("C6") == symmetry_number("C6h")\nTrue\n>>> symmetry_number("D2") == symmetry_number("Vh")\nTrue\n>>> symmetry_number("D4")\n8\n>>> symmetry_number("D6")\n12\n>>> symmetry_number("D6") == symmetry_number("D6d")\nTrue\n>>> symmetry_number("S6")\n3\n>>> symmetry_number("T")\n12\n
\n", "signature": "(point_group)", "funcdef": "def"}, {"fullname": "overreact.core", "modulename": "overreact.core", "type": "module", "doc": "

Module dedicated to parsing and modeling of chemical reaction networks.

\n"}, {"fullname": "overreact.core.Scheme", "modulename": "overreact.core", "qualname": "Scheme", "type": "class", "doc": "

A descriptor of a chemical reaction network.

\n\n

Mostly likely, this comes from a parsed input file.\nSee overreact.io.parse_model.

\n", "bases": "typing.NamedTuple"}, {"fullname": "overreact.core.Scheme.__init__", "modulename": "overreact.core", "qualname": "Scheme.__init__", "type": "function", "doc": "

Create new instance of Scheme(compounds, reactions, is_half_equilibrium, A, B)

\n", "signature": "(\n _cls,\n compounds: Sequence[str],\n reactions: Sequence[str],\n is_half_equilibrium: Sequence[bool],\n A: numpy.ndarray,\n B: numpy.ndarray\n)", "funcdef": "def"}, {"fullname": "overreact.core.Scheme.compounds", "modulename": "overreact.core", "qualname": "Scheme.compounds", "type": "variable", "doc": "

A descriptor of compounds.

\n", "annotation": ": Sequence[str]"}, {"fullname": "overreact.core.Scheme.reactions", "modulename": "overreact.core", "qualname": "Scheme.reactions", "type": "variable", "doc": "

A descriptor of reactions.

\n", "annotation": ": Sequence[str]"}, {"fullname": "overreact.core.Scheme.is_half_equilibrium", "modulename": "overreact.core", "qualname": "Scheme.is_half_equilibrium", "type": "variable", "doc": "

An indicator of whether a reaction is half-equilibrium.

\n", "annotation": ": Sequence[bool]"}, {"fullname": "overreact.core.Scheme.A", "modulename": "overreact.core", "qualname": "Scheme.A", "type": "variable", "doc": "

A matrix of stoichiometric coefficients between reactants and products.

\n", "annotation": ": numpy.ndarray"}, {"fullname": "overreact.core.Scheme.B", "modulename": "overreact.core", "qualname": "Scheme.B", "type": "variable", "doc": "

A matrix of stoichiometric coefficients between reactants and transition states.

\n", "annotation": ": numpy.ndarray"}, {"fullname": "overreact.core.parse_reactions", "modulename": "overreact.core", "qualname": "parse_reactions", "type": "function", "doc": "

Parse a kinetic model as a chemical reaction scheme.

\n\n

This is an essential part of the parsing process.\nSee overreact.io.parse_model other details.

\n\n
Parameters
\n\n
    \n
  • text (str or sequence of str):\nModel description or sequence of lines of it.
  • \n
\n\n
Returns
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.
  • \n
\n\n
Notes
\n\n

The model description should comply with the mini-language for systems of\nreactions. A semi-formal definition of the grammar in\nBackus\u2013Naur form\nis given below:

\n\n
     equation ::= equation_side arrow equation_side\nequation_side ::= coefficient compound ['+' coefficient compound]*\n  coefficient ::= [integers] (defaults to 1)\n     compound ::= mix of printable characters\n        arrow ::= '->' | '<=>' | '<-'\n
\n\n

Blank lines and comments (starting with //) are ignored. Repeated\nreactions are ignored. Furthermore, reactions can be chained one after\nanother and, if a single compound (with either a \u2021 or a # at the end)\nappears alone on one side of a reaction, it's considered a transition\nstate. Transition states have zero lifetime during the simulation.

\n\n
Examples
\n\n

What follows is a rather long tour over the parsing process and its\noutput in general. You can skip it if you are not interested in the\ndetails.

\n\n
>>> scheme = parse_reactions("A -> B  // a direct reaction")\n
\n\n

The reaction above is a direct one (observe that comments are ignored). The\nreturned object has the following attributes:

\n\n
>>> scheme.compounds\n('A', 'B')\n>>> scheme.reactions\n('A -> B',)\n>>> scheme.is_half_equilibrium\n(False,)\n>>> scheme.A\n((-1.,), (1.,))\n>>> scheme.B\n((-1.,), (1.,))\n
\n\n

The same reaction can be specified in reverse order:

\n\n
>>> parse_reactions("B <- A  // reverse reaction of the above")\nScheme(compounds=('A', 'B'),\n       reactions=('A -> B',),\n       is_half_equilibrium=(False,),\n       A=((-1.,), (1.,)),\n       B=((-1.,), (1.,)))\n
\n\n

Equilibria produce twice as many direct reactions, while the $B$ matrix\ndefines an energy relationship for only one of each pair:

\n\n
>>> parse_reactions("A <=> B  // an equilibrium")\nScheme(compounds=('A', 'B'),\n       reactions=('A -> B', 'B -> A'),\n       is_half_equilibrium=(True, True),\n       A=((-1.,  1.),\n          (1., -1.)),\n       B=((-1.,  0.),\n          (1.,  0.)))\n
\n\n

Adding twice the same reaction results in a single reaction being added.\nThis of course also works with equilibria (extra whitespaces are ignored):

\n\n
>>> parse_reactions('''\n...     A <=> B  -> A\n...     A  -> B <=> A\n...     A  -> B <-  A\n...     B <-  A  -> B\n... ''')\nScheme(compounds=('A', 'B'),\n       reactions=('A -> B', 'B -> A'),\n       is_half_equilibrium=(True, True),\n       A=((-1.,  1.),\n          (1., -1.)),\n       B=((-1.,  0.),\n          (1.,  0.)))\n
\n\n

Transition states are specified with a special symbol at the end (either\n\u2021 or #). They are shown among compounds, but the matrix $A$ ensures\nthey'll never have a non-zero rate of formation/consumption. On the other\nhand, they are needed in the $B$ matrix:

\n\n
>>> parse_reactions("A -> A\u2021 -> B")\nScheme(compounds=('A', 'A\u2021', 'B'),\n       reactions=('A -> B',),\n       is_half_equilibrium=(False,),\n       A=((-1.,), (0.,), (1.,)),\n       B=((-1.,), (1.,), (0.,)))\n
\n\n

This gives the same result as above:

\n\n
>>> parse_reactions("A -> A\u2021 -> B <- A\u2021 <- A")\nScheme(compounds=('A', 'A\u2021', 'B'),\n       reactions=('A -> B',),\n       is_half_equilibrium=(False,),\n       A=((-1.,), (0.,), (1.,)),\n       B=((-1.,), (1.,), (0.,)))\n
\n\n

It is possible to define a reaction whose product is the same as the\nreactant. This is found in isomerization processes (e.g., ammonia\ninversion or the methyl rotation in ethane):

\n\n
>>> parse_reactions("S -> E\u2021 -> S")\nScheme(compounds=('S', 'E\u2021'),\n       reactions=('S -> S',),\n       is_half_equilibrium=(False,),\n       A=((0.,), (0.,)),\n       B=((-1.,), (1.,)))\n
\n\n

As such, a column full of zeros in the $A$ matrix corresponds to a reaction\nwith zero net change. As can be seen, overreact allows for very general\nmodels. An interesting feature is that a single transition state can link\nmany different compounds (whether it is useful is a matter of debate):

\n\n
>>> parse_reactions('''\n...     B  -> B\u2021  -> C  // chained reactions and transition states\n...     B\u2021 -> D         // this is a bifurcation\n...     B  -> B'\u2021 -> E  // this is a classical competitive reaction\n...     A  -> B\u2021\n... ''')\nScheme(compounds=('B', 'B\u2021', 'C', 'D', "B'\u2021", 'E', 'A'),\n       reactions=('B -> C', 'B -> D', 'B -> E', 'A -> C', 'A -> D'),\n       is_half_equilibrium=(False, False, False, False, False),\n       A=((-1., -1., -1.,  0.,  0.),\n          (0.,  0.,  0.,  0.,  0.),\n          (1.,  0.,  0.,  1.,  0.),\n          (0.,  1.,  0.,  0.,  1.),\n          (0.,  0.,  0.,  0.,  0.),\n          (0.,  0.,  1.,  0.,  0.),\n          (0.,  0.,  0., -1., -1.)),\n       B=((-1., -1., -1.,  0.,  0.),\n          (1.,  1.,  0.,  1.,  1.),\n          (0.,  0.,  0.,  0.,  0.),\n          (0.,  0.,  0.,  0.,  0.),\n          (0.,  0.,  1.,  0.,  0.),\n          (0.,  0.,  0.,  0.,  0.),\n          (0.,  0.,  0., -1., -1.)))\n
\n\n

The following is a borderline case but both reactions should be considered\ndifferent since they define different processes:

\n\n
>>> parse_reactions('''\n...     A -> A\u2021 -> B\n...     A -> B\n... ''')\nScheme(compounds=('A', 'A\u2021', 'B'),\n       reactions=('A -> B', 'A -> B'),\n       is_half_equilibrium=(False, False),\n       A=((-1., -1.),\n          (0.,  0.),\n          (1.,  1.)),\n       B=((-1., -1.),\n          (1.,  0.),\n          (0.,  1.)))\n
\n\n

The following is correct behavior. In fact, the reactions are badly\ndefined: if more than one transition state are chained, the following\nhappens, which is correct since it's the most physically plausible model\nthat can be extracted. It can be seen as a feature that the product B is\nignored and not the reactant A, since the user would easily see the mistake\nin graphs of concentration over time (the alternative would be no\nreaction happening at all, which is rather cryptic to debug).

\n\n
>>> parse_reactions("A -> A\u2021 -> A'\u2021 -> B")\nScheme(compounds=('A', 'A\u2021', "A'\u2021", 'B'),\n       reactions=("A -> A'\u2021",),\n       is_half_equilibrium=(False,),\n       A=((-1.,), (0.,), (1.,), (0.,)),\n       B=((-1.,), (1.,), (0.,), (0.,)))\n
\n\n

In any case, it's not clear how a reaction barrier be defined in such a\ncase. If you have a use case, don't hesitate to\nopen an issue, we'll be\nhappy to hear from you.

\n", "signature": "(text: Union[str, Sequence[str]]) -> overreact.core.Scheme", "funcdef": "def"}, {"fullname": "overreact.io", "modulename": "overreact.io", "type": "module", "doc": "

Basic I/O operations (such as reading source input files).

\n"}, {"fullname": "overreact.io.parse_model", "modulename": "overreact.io", "qualname": "parse_model", "type": "function", "doc": "

Parse either a source or model input file, whichever is available.

\n\n

A source input file (also known as a .k file) contains all the information needed\nto create a model input file.\nA model input file (also known as a .jk file) is a JSON encoded file with all the\ninformation needed to study microkinetic simulations from first principles.

\n\n

You probably won't need to use model input files directly, they are\nautomatically created based on source input files.\nTake a look at our guide on how to write an source input file.

\n\n

This function attempts to parse a model input file if available. If not, a source\ninput file is parsed and a model input file is generated from it. Extensions are\nguessed if none given (i.e., if only the base name given).

\n\n
Parameters
\n\n
    \n
  • path (str):\nPath to the model or source input file.\nIf the final extension is not .jk or .k, it is guessed.
  • \n
  • force_compile (bool):\nIf True, a .k file will take precedence over any .jk file for reading. A\n.jk file is thus either generated or overwritten. This is sometimes\nneeded to force an update with new data.
  • \n
\n\n
Returns
\n\n
    \n
  • model (immutable dict-like):
  • \n
\n\n
Raises
\n\n
    \n
  • FileNotFoundError: If the model or source input file is not found.
  • \n
\n\n
Examples
\n\n

Some examples of how overreact \"sees\" your data below \ud83d\ude04:

\n\n
>>> model = parse_model("data/ethane/B97-3c/model.jk")\n>>> model.scheme\nScheme(compounds=('S', 'E\u2021'),\n       reactions=('S -> S',),\n       is_half_equilibrium=(False,),\n       A=((0.0,), (0.0,)),\n       B=((-1.0,), (1.0,)))\n>>> model.compounds["S"]\n{'logfile': 'data/ethane/B97-3c/staggered.out',\n 'energy': -209483812.77142256,\n 'mult': 1,\n 'atomnos': (6, 6, 1, 1, 1, 1, 1, 1),\n 'atommasses': (12.011, 12.011, 1.008, 1.008, 1.008, 1.008, 1.008, 1.008),\n 'atomcoords': ((-7.633588, 2.520693, -4.8e-05),\n                ...,\n                (-5.832852, 3.674431, 0.363239)),\n 'vibfreqs': (307.57, 825.42, ..., 3071.11, 3071.45),\n 'vibdisps': (((-1.7e-05, 3.4e-05, 5.4e-05),\n               ...,\n               (-0.011061, -0.030431, -0.027036)))}\n>>> model_from_source = parse_model("data/ethane/B97-3c/model.k",\n...                                 force_compile=True)\n>>> model_from_source == model\nTrue\n>>> model_from_source = parse_model("data/ethane/B97-3c/model")\n>>> model_from_source == model\nTrue\n
\n", "signature": "(path: str, force_compile: bool = False)", "funcdef": "def"}, {"fullname": "overreact.rates", "modulename": "overreact.rates", "type": "module", "doc": "

Module dedicated to the calculation of reaction rate constants.

\n"}, {"fullname": "overreact.rates.eyring", "modulename": "overreact.rates", "qualname": "eyring", "type": "function", "doc": "

Calculate a reaction rate constant.

\n\n

This function uses the Eyring-Evans-Polanyi equation\n from transition state\ntheory :

\n\n

$$k(T) = \\frac{k_\\text{B} T}{h} K^\\ddagger\n = \\frac{k_\\text{B} T}{h}\n \\exp\\left(-\\frac{\\Delta^\\ddagger G^\\circ}{R T}\\right)$$

\n\n

where \\( h \\) is Planck's constant, \\( k_\\text{B} \\) is Boltzmann's\nconstant and \\( T \\) is the absolute temperature.

\n\n
Parameters
\n\n
    \n
  • delta_freeenergy (array-like):\nDelta Gibbs activation free energies. This assumes values were already\ncorrected for a one molar reference state (if applicable).
  • \n
  • molecularity (array-like, optional):\nReaction order, i.e., number of molecules that come together to react.\nIf set, this is used to calculate delta_moles for\nequilibrium_constant, which effectively calculates a solution\nequilibrium constant between reactants and the transition state for\ngas phase data. You should set this to None if your free energies\nwere already adjusted for solution Gibbs free energies.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
  • volume (float, optional):\nMolar volume. This is passed on to equilibrium_constant.
  • \n
\n\n
Returns
\n\n
    \n
  • k (array-like):\nReaction rate constant(s). By giving energies in one molar reference\nstate, returned units are then accordingly given, e.g. \"l mol-1 s-1\"\nif second-order, etc.
  • \n
\n\n
Notes
\n\n

This function uses equilibrium_constant internally to calculate the\nequilibrium constant between reactants and the transition state.

\n\n
Examples
\n\n

The following are examples from\nThermochemistry in Gaussian, in which the\nkinetic isotope effect of a bimolecular reaction is analyzed:

\n\n
>>> eyring(17.26 * constants.kcal)\narray([1.38])\n>>> eyring(18.86 * constants.kcal)\narray([0.093])\n
\n\n

It is well known that, at room temperature, if you \"decrease\" a reaction\nbarrier by 1.4 kcal/mol, the reaction becomes around ten times faster:

\n\n
>>> dG = np.random.uniform(1.0, 100.0) * constants.kcal\n>>> eyring(dG - 1.4 * constants.kcal) / eyring(dG)\narray([10.])\n
\n\n

A similar relationship is found for a twofold increase in speed and a\n0.4 kcal/mol decrease in the reaction barrier (again, at room\ntemperature):

\n\n
>>> eyring(dG - 0.4 * constants.kcal) / eyring(dG)\narray([2.0])\n
\n", "signature": "(\n delta_freeenergy: Union[float, numpy.ndarray],\n molecularity: Optional[int] = None,\n temperature: Union[float, numpy.ndarray] = 298.15,\n pressure: float = 101325.0,\n volume: Optional[float] = None\n)", "funcdef": "def"}, {"fullname": "overreact.simulate", "modulename": "overreact.simulate", "type": "module", "doc": "

Module dedicated to the time simulation of reaction models.

\n\n

Here are functions that calculate reaction rates as well, which is needed for\nthe time simulations.

\n"}, {"fullname": "overreact.simulate.get_y", "modulename": "overreact.simulate", "qualname": "get_y", "type": "function", "doc": "

Simulate a reaction scheme from its rate function.

\n\n

This function provides two functions that calculate the concentrations and\nthe rates of formation at any point in time for any compound. It does that\nby solving an initial value problem (IVP) through scipy's solve_ivp\nunder the hood.

\n\n
Parameters
\n\n
    \n
  • dydt (callable):\nRight-hand side of the system.
  • \n
  • y0 (array-like):\nInitial state.
  • \n
  • t_span (array-like, optional):\nInterval of integration (t0, tf). The solver starts with t=t0 and\nintegrates until it reaches t=tf. If not given, a conservative value\nis chosen based on the system at hand (the method of choice works for\nany zeroth-, first- or second-order reactions).
  • \n
  • method (str, optional):\nIntegration method to use. See scipy.integrate.solve_ivp for details.\nKinetics problems are very often stiff and, as such, \"RK45\" is\nnormally unsuited. \"Radau\", \"BDF\" or \"LSODA\" are good choices.
  • \n
  • rtol, atol (array-like):\nSee scipy.integrate.solve_ivp for details.
  • \n
  • max_time (float, optional):\nIf t_span is not given, an interval will be estimated, but it can't\nbe larger than this parameter.
  • \n
\n\n
Returns
\n\n
    \n
  • y, r (callable):\nConcentrations and reaction rates as functions of time. The y object\nis an OdeSolution and stores attributes t_min and t_max.
  • \n
\n\n
Examples
\n\n
>>> import numpy as np\n>>> import overreact as rx\n
\n\n

A toy simulation can be performed in just two lines:

\n\n
>>> scheme = rx.parse_reactions("A <=> B")\n>>> y, r = get_y(get_dydt(scheme, np.array([1, 1])), y0=[1, 0])\n
\n\n

The y object stores information about the simulation time, which can be\nused to produce a suitable vector of timepoints for, e.g., plotting:

\n\n
>>> y.t_min, y.t_max  # doctest: +SKIP\n(0.0, 3.0)\n>>> t = np.linspace(y.t_min, y.t_max)\n>>> t  # doctest: +SKIP\narray([0. , 0.06122449, ..., 2.93877551, 3. ])\n
\n\n

Both y and r can be used to check concentrations and rates in any\npoint in time. In particular, both are vectorized:

\n\n
>>> y(t)  # doctest: +SKIP\narray([[1. , 0.94237559, ..., 0.5012394, 0.5 ],\n       [0. , 0.05762441, ..., 0.4987606, 0.5 ]])\n>>> r(t)  # doctest: +SKIP\narray([[-1.00000000e+00, ..., -1.39544265e-10],\n       [ 1.00000000e+00, ...,  1.39544265e-10]])\n
\n", "signature": "(\n dydt,\n y0,\n t_span=None,\n method='Radau',\n rtol=1e-05,\n atol=1e-11,\n max_time=86400\n)", "funcdef": "def"}, {"fullname": "overreact.simulate.get_dydt", "modulename": "overreact.simulate", "qualname": "get_dydt", "type": "function", "doc": "

Generate a rate function that models a reaction scheme.

\n\n
Parameters
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.\nMostly likely, this comes from a parsed model input file.\nSee overreact.io.parse_model.
  • \n
  • k (array-like):\nReaction rate constant(s). Units match the concentration units given to\nthe returned function dydt.
  • \n
  • ef (float, optional):\nEquilibrium factor. This is a parameter that can be used to scale the\nreaction rates associated to half-equilibrium reactions such that they\nare faster than the other reactions.
  • \n
\n\n
Returns
\n\n
    \n
  • dydt (callable):\nReaction rate function. The actual reaction rate constants employed\nare stored in the attribute k of the returned function. If JAX is\navailable, the attribute jac will hold the Jacobian function of\ndydt.
  • \n
\n\n
Notes
\n\n

The returned function is suited to be used by ODE solvers such as\nscipy.integrate.solve_ivp or the older scipy.integrate.ode (see\nexamples below). This is actually what the function get_y from the\ncurrent module does.

\n\n
Examples
\n\n
>>> import numpy as np\n>>> import overreact as rx\n
\n\n
>>> scheme = rx.parse_reactions("A <=> B")\n>>> dydt = get_dydt(scheme, np.array([1, 1]))\n>>> dydt(0.0, np.array([1., 1.]))  # doctest: +SKIP\narray([0., 0.])\n
\n\n

If available, JAX is used for JIT compilation. This will make dydt\ncomplain if given lists instead of numpy arrays. So stick to the safer,\nfaster side as above.

\n\n

The actually used reaction rate constants can be inspected with the k\nattribute of dydt:

\n\n
>>> dydt.k  # doctest: +SKIP\narray([1., 1.])\n
\n\n

If JAX is available, the Jacobian function will be available as\ndydt.jac:

\n\n
>>> dydt.jac(0.0, np.array([1., 1.]))  # doctest: +SKIP\nDeviceArray([[-1.,  1.],\n             [ 1., -1.]], dtype=float64)\n
\n", "signature": "(scheme, k, ef=5)", "funcdef": "def"}, {"fullname": "overreact.simulate.get_fixed_scheme", "modulename": "overreact.simulate", "qualname": "get_fixed_scheme", "type": "function", "doc": "

Generate an alternative scheme with some concentrations fixed.

\n\n

This function returns data that allow the microkinetic simulation of a\nreaction network under constraints, namely when some compounds have fixed\nconcentrations. This works by 1. removing all references to the fixed\ncompounds and by 2. properly multiplying the reaction rate constants by\nthe respective concentrations.

\n\n
Parameters
\n\n
    \n
  • scheme (Scheme):\nA descriptor of the reaction scheme.\nMostly likely, this comes from a parsed model input file.\nSee overreact.io.parse_model.
  • \n
  • k (array-like):\nReaction rate constant(s). Units match the concentration units given to\nthe returned function dydt.
  • \n
  • fixed_y0 (dict-like):\nFixed initial state. Units match the concentration units given to\nthe returned function dydt.
  • \n
\n\n
Returns
\n\n
    \n
  • scheme (Scheme):\nAssociated reaction scheme with all references to fixed compounds\nremoved.
  • \n
  • k (array-like):\nAssociated (effective) reaction rate constants that model the fixed\nconcentrations.
  • \n
\n\n
Notes
\n\n

Keep in mind that when a compound get its concentration fixed, the\nreaction scheme no longer conserves matter. You can think of it as\nreacting close to an infinite source of the compound, but it accumulates\nin the milleu at the given concentration.

\n\n
Examples
\n\n
>>> import numpy as np\n>>> import overreact as rx\n
\n\n

Equilibria under a specific pH can be easily modeled:

\n\n
>>> pH = 7\n>>> scheme = rx.parse_reactions("AH <=> A- + H+")\n>>> k = np.array([1, 1])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H+": 10**-pH})\n>>> scheme\nScheme(compounds=('AH', 'A-'),\n       reactions=('AH -> A-',\n                  'A- -> AH'),\n       is_half_equilibrium=(True, True),\n       A=((-1.0, 1.0),\n          (1.0, -1.0)),\n       B=((-1.0, 0.0),\n          (1.0, 0.0)))\n>>> k\narray([1.e+00, 1.e-07])\n
\n\n

It is also possible to model the fixed activity of a solvent, for\ninstance:

\n\n
>>> scheme = rx.parse_reactions("A + 2H2O -> B")\n>>> k = np.array([1.0])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H2O": 55.6})\n>>> scheme\nScheme(compounds=('A', 'B'),\n       reactions=('A -> B',),\n       is_half_equilibrium=(False,),\n       A=((-1.0,),\n          (1.0,)),\n       B=((-1.0,),\n          (1.0,)))\n>>> k\narray([3091.36])\n
\n\n

Multiple reactions work fine, see both examples below:

\n\n
>>> pH = 12\n>>> scheme = rx.parse_reactions("B <- AH <=> A- + H+")\n>>> k = np.array([10.0, 1, 1])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H+": 10**-pH})\n>>> scheme\nScheme(compounds=('AH', 'B', 'A-'),\n       reactions=('AH -> B',\n                  'AH -> A-',\n                  'A- -> AH'),\n       is_half_equilibrium=(False, True, True),\n       A=((-1.0, -1.0, 1.0),\n          (1.0, 0.0, 0.0),\n          (0.0, 1.0, -1.0)),\n       B=((-1.0, -1.0, 0.0),\n          (1.0, 0.0, 0.0),\n          (0.0, 1.0, 0.0)))\n>>> k\narray([1.e+01, 1.e+00, 1.e-12])\n
\n\n
>>> pH = 2\n>>> scheme = rx.parse_reactions(["AH <=> A- + H+", "B- + H+ <=> BH"])\n>>> k = np.array([1, 1, 2, 2])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H+": 10**-pH})\n>>> scheme\nScheme(compounds=('AH', 'A-', 'B-', 'BH'),\n       reactions=('AH -> A-',\n                  'A- -> AH',\n                  'B- -> BH',\n                  'BH -> B-'),\n       is_half_equilibrium=(True, True, True, True),\n       A=((-1.0, 1.0, 0.0, 0.0),\n          (1.0, -1.0, 0.0, 0.0),\n          (0.0, 0.0, -1.0, 1.0),\n          (0.0, 0.0, 1.0, -1.0)),\n       B=((-1.0, 0.0, 0.0, 0.0),\n          (1.0, 0.0, 0.0, 0.0),\n          (0.0, 0.0, -1.0, 0.0),\n          (0.0, 0.0, 1.0, 0.0)))\n>>> k\narray([1. , 0.01, 0.02, 2. ])\n
\n\n

Multiple fixed compounds also work fine:

\n\n
>>> pH = 6\n>>> scheme = rx.parse_reactions("A + H2O -> B <=> B- + H+")\n>>> k = np.array([1.0, 100.0, 2.0])\n>>> scheme, k = rx.get_fixed_scheme(scheme, k, {"H+": 10**-pH, "H2O": 55.6})\n>>> scheme\nScheme(compounds=('A', 'B', 'B-'),\n       reactions=('A -> B',\n                  'B -> B-',\n                  'B- -> B'),\n       is_half_equilibrium=(False, True, True),\n       A=((-1.0, 0.0, 0.0),\n          (1.0, -1.0, 1.0),\n          (0.0, 1.0, -1.0)),\n       B=((-1.0, 0.0, 0.0),\n          (1.0, -1.0, 0.0),\n          (0.0, 1.0, 0.0)))\n>>> k\narray([5.56e+01, 1.00e+02, 2.00e-06])\n
\n\n

This function is a no-op if fixed_y0 is empty, which is very important\nfor overall code consistency:

\n\n
>>> scheme = rx.parse_reactions(["AH <=> A- + H+", "B- + H+ <=> BH"])\n>>> k = np.array([1, 1, 2, 2])\n>>> new_scheme, new_k = rx.get_fixed_scheme(scheme, k, {})\n>>> new_scheme == scheme\nTrue\n>>> np.allclose(new_k, k)\nTrue\n
\n", "signature": "(scheme, k, fixed_y0)", "funcdef": "def"}, {"fullname": "overreact.thermo", "modulename": "overreact.thermo", "type": "module", "doc": "

Module dedicated to the calculation of thermodynamic properties.

\n"}, {"fullname": "overreact.thermo.equilibrium_constant", "modulename": "overreact.thermo", "qualname": "equilibrium_constant", "type": "function", "doc": "

Calculate an equilibrium constant from a reaction Gibbs free energy.

\n\n

This function uses the usual relationship between reaction Gibbs energy\nand equilibrium constant\n:

\n\n

$$K(T) = \\exp\\left(-\\frac{\\Delta_\\text{r} G^\\circ}{R T}\\right)$$

\n\n

If delta_moles is given, the above will be multiplied by a term\n\\( \\left( \\frac{R T}{p} \\right)^{-\\Delta n} \\), which effectively\ntransforms a \\( K_p \\) equilibrium constant into a \\( K_c \\)\n(see below).

\n\n
Parameters
\n\n
    \n
  • delta_freeenergy (array-like):\nDelta Gibbs reaction free energies. This assumes values were already\ncorrected for a one molar reference state.
  • \n
  • delta_moles (array-like, optional):\nDifference in moles between products and reactants. If set, this\nmultiplies the end result by\n\\( \\left( \\frac{R T}{p} \\right)^{-\\Delta n} \\), which effectively\ncalculates a solution equilibrium constant for gas phase data. You\nshould set this to None if your free energies were already adjusted\nfor solution Gibbs free energies.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
  • volume (float, optional):\nMolar volume. This substitutes \\( \\frac{R T}{p} \\) if given. See\ndelta_moles.
  • \n
\n\n
Returns
\n\n
    \n
  • K (array-like):\nEquilibrium constant.
  • \n
\n\n
Notes
\n\n

If you want to calculate a solution equilibrium constant from gas phase data, set\ndelta_moles to the difference in moles between products and reactants.\nAlternatively, convert your energies to solution Gibbs free energies and\nset delta_moles to None.

\n\n
Examples
\n\n

The following is an example from the\nLibreTexts Chemistry Library.\nConsider the following equilibrium:

\n\n

$$\\ce{2 SO2(g) + O2(g) <=> 2 SO3(g)}$$

\n\n

with concentrations \\( c_{\\ce{SO2(g)}} = 0.2 M \\),\n\\( c_{\\ce{O2(g)}} = 0.5 M \\) and \\( c_{\\ce{SO3(g)}} = 0.7 M \\) (room\ntemperature). Its \\( K_c \\) is given by:

\n\n
>>> Kc = 0.7**2 / (0.2**2 * 0.5)\n>>> Kc\n24.5\n
\n\n

You could use equilibrium_constant to reach the same result using the\nGibbs reaction free energy (which can easily be obtained from\n\\( K_c \\)):

\n\n
>>> temperature = 298.15\n>>> dG = -constants.R * temperature * np.log(Kc)\n>>> equilibrium_constant(dG)\narray([24.5])\n
\n\n

By giving a delta_moles value (in this case, \\( 2 - 2 - 1 = -1 \\)),\nwe can calculate the corresponding K_p:

\n\n
>>> equilibrium_constant(dG, delta_moles=-1)\narray([1.002])\n
\n\n

(As expected, it makes sense for gases to favor the most entropic side of\nthe equilibrium.) The example above clearly used \"solution-based\" data\n(our \\( K_c \\) was calculated using molar quantities, which means\nreference volumes of one liter). You could convert it to gas phase data\nto get the same result, by changing the reference state (in this case,\nfrom one molar to one atmosphere using change_reference_state):

\n\n
>>> dG += temperature * rx.change_reference_state()\n>>> equilibrium_constant(dG)\narray([1.002])\n
\n\n

Having gas phase information, the inverse path can be taken just by\ninverting the sign of delta_moles:

\n\n
>>> equilibrium_constant(dG, delta_moles=1)\narray([24.5])\n
\n\n

The following example is from\nWikipedia.\nThe reactions are two copper complex forming equilibria with two\ndifferent ligands. Since this reaction takes place in solution, it is the\nsolution standard Gibbs reaction free energy that is given:

\n\n
>>> dG1 = -37.4e3\n>>> np.log10(equilibrium_constant(dG1))\narray([6.55])\n>>> dG2 = -60.67e3\n>>> np.log10(equilibrium_constant(dG2))\narray([10.62])\n
\n\n

The above are thus \\( \\log_{10}(K_c) \\). Since we are talking about a\nmono- and a bidendate ligands, the delta_moles are -4 and -2,\nrespectively, and we could obtain the \\( \\log_{10}(K_p) \\) the following\nway:

\n\n
>>> np.log10(equilibrium_constant(dG1, delta_moles=-4))\narray([0.998])\n>>> np.log10(equilibrium_constant(dG2, delta_moles=-2))\narray([7.85])\n
\n\n

You can easily check that the above values match the values given\nhere.

\n", "signature": "(\n delta_freeenergy: Union[float, numpy.ndarray],\n delta_moles: Union[int, numpy.ndarray, NoneType] = None,\n temperature: Union[float, numpy.ndarray] = 298.15,\n pressure: float = 101325.0,\n volume: Optional[float] = None\n)", "funcdef": "def"}, {"fullname": "overreact.thermo.change_reference_state", "modulename": "overreact.thermo", "qualname": "change_reference_state", "type": "function", "doc": "

Calculate an additive entropy correction to a change in reference states.

\n\n

$$\\Delta G_\\text{corr} =\n R T \\ln \\left( \\frac{\\chi_\\text{new}}{\\chi_\\text{old}} \\right)$$

\n\n

The value returned can be directly multiplied by temperature and summed to\nthe old reference free energies to obtain free energies with respect to a\nnew reference. See notes below.

\n\n

For instance, the concentration correction to Gibbs free energy for a\ngas-to-liquid standard state change is simply\n(\\( c^\\circ = \\frac{\\text{1 atm}}{R T} \\)),

\n\n

$$\\Delta G_\\text{conc} =\n R T \\ln \\left( \\frac{\\text{1 M}}{c^\\circ} \\right)$$

\n\n
Parameters
\n\n
    \n
  • new_reference (array-like, optional):\nNew reference state. Default value corresponds to 1 mol/liter.
  • \n
  • old_reference (array-like, optional):\nOld reference state. Default value corresponds to the concentration of\nan ideal gas at the given temperature and 1 atm.
  • \n
  • sign (float, optional):\nSign of the change in reference state. Default value is 1. This only\nmultiplies the final result.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
  • pressure (array-like, optional):\nReference gas pressure.
  • \n
  • volume (float, optional):\nMolar volume.
  • \n
\n\n
Returns
\n\n
    \n
  • correction (array-like):\nEntropy correction in J/mol\u00b7K.
  • \n
\n\n
Notes
\n\n

This function can be used to add any entropy correction in the form above.\nThe only drawback is that, sometimes, those corrections are written with a\nminus sign in front of them (this implies switching the roles of\nold_reference and new_reference). The easiest way to accomplish this is\nby using sign=-1 or multiplying the result by -1.

\n\n
Examples
\n\n

By default, the correction returns a change in concentration from the gas\nphase standard concentration to the solvated-state standard concentration:

\n\n
>>> -rx.change_reference_state() / constants.calorie\n-6.4\n>>> 298.15 * rx.change_reference_state() / constants.kcal\n1.89\n>>> 273.15 * rx.change_reference_state(temperature=273.15) / constants.kcal\n1.69\n
\n\n

But this function can also be used to adjust symmetry effects from C1\ncalculations (symmetry number equals to one). For D7h, for instance, the\nsymmetry number is 14:

\n\n
>>> -298.15 * rx.change_reference_state(14, 1) / constants.kcal\n-1.56\n
\n\n
>>> rx.change_reference_state(sign=-1) == -rx.change_reference_state()\nTrue\n
\n", "signature": "(\n new_reference: float = 1000.0,\n old_reference: Optional[float] = None,\n sign: int = 1,\n temperature: Union[float, numpy.ndarray] = 298.15,\n pressure: float = 101325.0,\n volume: Optional[float] = None\n)", "funcdef": "def"}, {"fullname": "overreact.tunnel", "modulename": "overreact.tunnel", "type": "module", "doc": "

Module dedicated to quantum tunneling approximations.

\n"}, {"fullname": "overreact.tunnel.eckart", "modulename": "overreact.tunnel", "qualname": "eckart", "type": "function", "doc": "

Calculate the Eckart correction to quantum tunneling.

\n\n

References are\nJ. Phys. Chem. 1962, 66, 3, 532\u2013533\nand\nJ. Res. Natl. Inst. Stand. Technol., 1981, 86, 357.

\n\n
Parameters
\n\n
    \n
  • vibfreq (array-like):\nMagnitude of the imaginary frequency in cm$^{-1}$. Only the absolute value\nis used.
  • \n
  • delta_forward (array-like):\nActivation enthalpy at 0 K for the forward reaction.
  • \n
  • delta_backward (array-like, optional):\nActivation enthalpy at 0 K for the reverse reaction. If delta_backward\nis not given, the \"symmetrical\" Eckart model is used (i.e.,\ndelta_backward == delta_forward is assumed).
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • kappa (array-like):\nThe quantum tunneling correction.
  • \n
\n\n
Raises
\n\n
    \n
  • ValueError: If vibfreq is zero.
  • \n
\n\n
Examples
\n\n
>>> eckart(1218, 13672.624, 24527.729644, temperature=300)\narray(3.9)\n>>> eckart(1218, 13672.624, 24527.729644, temperature=[200, 298.15])\narray([17.1, 4.0])\n>>> eckart([1218, 200], 13672.624, 24527.729644, temperature=400)\narray([2.3, 1.0])\n
\n\n

If no backward barrier is given, a symmetric Eckart potential is assumed:

\n\n
>>> eckart(414.45, 394.54)\narray(1.16)\n>>> eckart(414.45, 789.08)\narray(1.3)\n>>> eckart(3315.6, 3156.31)\narray(3.3)\n
\n", "signature": "(\n vibfreq: float,\n delta_forward: float,\n delta_backward: Optional[float] = None,\n temperature: Union[float, numpy.ndarray] = 298.15\n) -> Union[float, numpy.ndarray]", "funcdef": "def"}, {"fullname": "overreact.tunnel.wigner", "modulename": "overreact.tunnel", "qualname": "wigner", "type": "function", "doc": "

Calculate the Wigner correction to quantum tunneling.

\n\n
Parameters
\n\n
    \n
  • vibfreq (array-like):\nMagnitude of the imaginary frequency in cm$^{-1}$. Only the absolute value\nis used.
  • \n
  • temperature (array-like, optional):\nAbsolute temperature in Kelvin.
  • \n
\n\n
Returns
\n\n
    \n
  • kappa (array-like):\nThe quantum tunneling correction.
  • \n
\n\n
Raises
\n\n
    \n
  • ValueError: If vibfreq is zero.
  • \n
\n\n
Examples
\n\n
>>> wigner(1821.0777)\n4.218\n>>> wigner(262.38)\n1.06680\n>>> wigner(113.87)\n1.01258\n>>> wigner(169.14)\n1.02776\n
\n", "signature": "(\n vibfreq: float,\n temperature: Union[float, numpy.ndarray] = 298.15\n) -> float", "funcdef": "def"}]; // mirrored in build-search-index.js (part 1) // Also split on html tags. this is a cheap heuristic, but good enough.