diff --git a/examples/pyreactlab-core/README.md b/examples/pyreactlab-core/README.md
new file mode 100644
index 0000000..3834d58
--- /dev/null
+++ b/examples/pyreactlab-core/README.md
@@ -0,0 +1,18 @@
+# pyreactlab-core Examples
+
+Each sub-directory contains a self-contained example. The order in
+which the examples are to appear is specified in `order.json` (an
+array of directory names in the expected order).
+
+In each example directory you'll find:
+
+* `config.toml` - must conform to the specification outlined here:
+ https://docs.pyscript.net/latest/user-guide/configuration/ This is
+ parsed and ultimately turned into a JSON representation as part of
+ the package's API object.
+* `setup.py` - Python code for contextual and environmental setup,
+ NOT SEEN BY THE END USER, but is run before the `code.py` code is
+ evaluated. Allows us to create useful (IPython) shims, avoid
+ repeating boilerplate and whatnot.
+* `code.py` - the actual code added to the editor which forms the
+ practical example of using the package.
diff --git a/examples/pyreactlab-core/introduce_a_reaction/code.py b/examples/pyreactlab-core/introduce_a_reaction/code.py
new file mode 100644
index 0000000..8c8095e
--- /dev/null
+++ b/examples/pyreactlab-core/introduce_a_reaction/code.py
@@ -0,0 +1,49 @@
+"""
+A first look at PyReactLab-Core.
+
+We'll define a chemical reaction as a string and let the package parse
+it into structured information: reactants, products, stoichiometric
+coefficients, phases, and more.
+
+Docs: https://pyreactlab-core.readthedocs.io/
+"""
+from IPython.core.display import display, HTML
+# Package imports for the first example.
+from pyreactlab_core.models.reaction import Reaction
+
+
+heading("Methanol synthesis from CO2 and hydrogen")
+note(
+ "We describe the reaction with a compact string. The "
+ "(g) markers tell PyReactLab the phase of each "
+ "species, and => separates reactants from products."
+)
+
+methanol_synthesis = Reaction(
+ name="CO2 Hydrogenation to Methanol",
+ reaction="CO2(g) + 3H2(g) => CH3OH(g) + H2O(g)",
+)
+
+note(f"Parsed reaction string: {methanol_synthesis.reaction}")
+
+# A small HTML table summarising the parsed properties.
+properties = {
+ "Reactants": methanol_synthesis.reactants_names,
+ "Products": methanol_synthesis.products_names,
+ "Reaction phase": methanol_synthesis.reaction_phase,
+ "State counts": methanol_synthesis.state_count,
+ "Stoichiometry": methanol_synthesis.reaction_stoichiometry,
+ "Carbon count per species": methanol_synthesis.carbon_count,
+}
+
+rows = "".join(
+ f"
{v}{text}
"), append=True) + diff --git a/examples/pyreactlab-core/order.json b/examples/pyreactlab-core/order.json new file mode 100644 index 0000000..33a06f0 --- /dev/null +++ b/examples/pyreactlab-core/order.json @@ -0,0 +1,4 @@ +[ + "introduce_a_reaction", + "stoichiometry_matrix" +] diff --git a/examples/pyreactlab-core/stoichiometry_matrix/code.py b/examples/pyreactlab-core/stoichiometry_matrix/code.py new file mode 100644 index 0000000..baef7c9 --- /dev/null +++ b/examples/pyreactlab-core/stoichiometry_matrix/code.py @@ -0,0 +1,72 @@ +# --------------------------------------------------------------------- +# Section 2: Build a stoichiometry matrix for a small reaction network. +# --------------------------------------------------------------------- +import pandas as pd +from pyreactlab_core.models.reaction import Reaction +from pyreactlab_core import rxn, rxns_stoichiometry + + +heading("A two-reaction hydrogenation network") +note( + "PyReactLab can take a list of reactions and assemble the " + "stoichiometry matrix you'd use in reactor design or " + "reaction-engineering math. Negative entries mean a species is " + "consumed; positive entries mean it's produced." +) + +# Use the convenience constructor `rxn` to build Reaction instances. +methanol_synthesis = rxn( + reaction_str="CO2(g) + 3H2(g) => CH3OH(g) + H2O(g)", + name="CO2 Hydrogenation to Methanol", +) + +ethylene_hydrogenation = rxn( + reaction_str="C2H4(g) + H2(g) => C2H6(g)", + name="Ethylene Hydrogenation to Ethane", +) + +reactions = [methanol_synthesis, ethylene_hydrogenation] + +# Assemble the stoichiometry matrix across the union of all species. +matrix_info = rxns_stoichiometry(reactions=reactions) + +# Note: despite the "_dict" suffix, `stoichiometry_matrices_dict` is a +# list of per-reaction dicts (one {species: coefficient} mapping per +# reaction), aligned with the input `reactions` order. Pandas handles +# this shape natively when given a list of records, inferring columns +# from the union of keys. +rows = matrix_info["stoichiometry_matrices_dict"] + +stoich_df = pd.DataFrame( + rows, + index=[r.name for r in reactions], +) + +# Reindex to the canonical species ordering from `component_list`, so +# the column order is stable rather than dict-iteration-dependent. +stoich_df = stoich_df.reindex(columns=matrix_info["component_list"]) + +note("Rows are reactions, columns are species (with phase suffixes):") +display(stoich_df, append=True) + +heading("Quick sanity checks", level=3) + +# Net mole change per reaction: sum of stoichiometric coefficients across +# all species. A negative value means the reaction consumes more moles of +# gas than it produces, which matters for reactor pressure and volume +# calculations. (This is not a mass balance — that would require weighting +# each coefficient by the species' molecular weight.) +net_change = stoich_df.sum(axis=1).rename("net mole change") +display(net_change.to_frame(), append=True) + +note( + "Methanol synthesis shows a net change of -2 moles: four moles of " + "gas in (1 CO2 + 3 H2) become two moles out " + "(1 CH3OH + 1 H2O). Ethylene hydrogenation " + "loses one mole (2 in, 1 out). Both reactions favour higher " + "pressure by Le Chatelier's principle." +) + +# Which reactions consume H2? +h2_consumers = stoich_df.index[stoich_df["H2-g"] < 0].tolist() +note(f"Reactions that consume H2(g): {h2_consumers}") \ No newline at end of file diff --git a/examples/pyreactlab-core/stoichiometry_matrix/config.toml b/examples/pyreactlab-core/stoichiometry_matrix/config.toml new file mode 100644 index 0000000..ec65502 --- /dev/null +++ b/examples/pyreactlab-core/stoichiometry_matrix/config.toml @@ -0,0 +1 @@ +packages = ["pyreactlab-core", "pandas"] diff --git a/examples/pyreactlab-core/stoichiometry_matrix/setup.py b/examples/pyreactlab-core/stoichiometry_matrix/setup.py new file mode 100644 index 0000000..475e0e4 --- /dev/null +++ b/examples/pyreactlab-core/stoichiometry_matrix/setup.py @@ -0,0 +1,20 @@ +"""Setup for the stoichiometry matrix example.""" +import js +from pyscript import window, HTML, display as _display + +js.alert = window.alert + + +def display(*args, **kwargs): + return _display( + *args, **kwargs, target=__pyscript_display_target__, + ) + + +def heading(text, level=2): + display(HTML(f"{text}
"), append=True) +