A <-> 2C + D, with 1st-order kinetics for each species, taken to equilibrium¶Diffusion not applicable (just 1 bin)
LAST REVISED: July 14, 2023
import set_path # Importing this module will add the project's home directory to sys.path
Added 'D:\Docs\- MY CODE\BioSimulations\life123-Win7' to sys.path
from experiments.get_notebook_info import get_notebook_basename
from src.modules.chemicals.chem_data import ChemData as chem
from src.life_1D.bio_sim_1d import BioSim1D
import plotly.express as px
from src.modules.visualization.graphic_log import GraphicLog
# Initialize the HTML logging
log_file = get_notebook_basename() + ".log.htm" # Use the notebook base filename for the log file
# Set up the use of some specified graphic (Vue) components
GraphicLog.config(filename=log_file,
components=["vue_cytoscape_1"],
extra_js="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.21.2/cytoscape.umd.js")
-> Output will be LOGGED into the file 'reaction_5.log.htm'
# Initialize the system
chem_data = chem(names=["A", "C", "D"]) # NOTE: Diffusion not applicable (just 1 bin)
# Reaction A <-> 2C + D , with 1st-order kinetics for each species
chem_data.add_reaction(reactants=[("A")], products=[(2, "C") , ("D")],
forward_rate=5., reverse_rate=2.)
bio = BioSim1D(n_bins=1, chem_data=chem_data)
bio.set_all_uniform_concentrations( [4., 7., 2.] )
bio.describe_state()
SYSTEM STATE at Time t = 0: 1 bins and 3 species: Species 0 (A). Diff rate: None. Conc: [4.] Species 1 (C). Diff rate: None. Conc: [7.] Species 2 (D). Diff rate: None. Conc: [2.]
# Save the state of the concentrations of all species at bin 0
bio.add_snapshot(bio.bin_snapshot(bin_address = 0), caption="Initial state")
bio.get_history()
| SYSTEM TIME | A | C | D | caption | |
|---|---|---|---|---|---|
| 0 | 0 | 4.0 | 7.0 | 2.0 | Initial state |
chem_data.describe_reactions()
Number of reactions: 1 (at temp. 25 C) 0: A <-> 2 C + D (kF = 5 / kR = 2 / Delta_G = -2,271.45 / K = 2.5) | 1st order in all reactants & products
# Send the plot to the HTML log file
graph_data = chem_data.prepare_graph_network()
GraphicLog.export_plot(graph_data, "vue_cytoscape_1")
[GRAPHIC ELEMENT SENT TO LOG FILE `reaction_5.log.htm`]
# First step
bio.react(time_step=0.2, n_steps=1)
bio.describe_state()
SYSTEM STATE at Time t = 0.2: 1 bins and 3 species: Species 0 (A). Diff rate: None. Conc: [5.6] Species 1 (C). Diff rate: None. Conc: [3.8] Species 2 (D). Diff rate: None. Conc: [0.4]
Note: the above values are quite inaccurate because of the large time step 0.2
For example, the value for the concentration of D (0.4) is a wild overshot from the initial 2.0 to the equilibrium value of 1.68941267
A more precise calculation with bio.react(time_step=0.1, n_steps=2) gives conc_D(0.2) = 2.304
An even more precise calculation with bio.react(time_step=0.05, n_steps=4) gives conc_D(0.2) = 1.69037202
I.e. the system is almost at equilibrium already at t=0.2 !
TODO: explore the early dynamics of the system in a separate experiment
# Save the state of the concentrations of all species at bin 0
bio.add_snapshot(bio.bin_snapshot(bin_address = 0))
bio.get_history()
| SYSTEM TIME | A | C | D | caption | |
|---|---|---|---|---|---|
| 0 | 0.0 | 4.0 | 7.0 | 2.0 | Initial state |
| 1 | 0.2 | 5.6 | 3.8 | 0.4 |
# Numerous more steps
bio.react(time_step=0.05, n_steps=30, snapshots={"sample_bin": 0})
bio.describe_state()
SYSTEM STATE at Time t = 1.7: 1 bins and 3 species: Species 0 (A). Diff rate: None. Conc: [4.31058733] Species 1 (C). Diff rate: None. Conc: [6.37882534] Species 2 (D). Diff rate: None. Conc: [1.68941267]
Consistent with the 5/2 ratio of forward/reverse rates (and the 1st order reactions),
the systems settles in the following equilibrium:
[A] = 4.31058733 , [C] = 6.37882534 , [D] = 1.68941267
# Verify that the reaction has reached equilibrium
bio.reaction_dynamics.is_in_equilibrium(rxn_index=0, conc=bio.bin_snapshot(bin_address = 0))
A <-> 2 C + D
Final concentrations: [C] = 6.379 ; [D] = 1.689 ; [A] = 4.311
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 2.5
Formula used: ([C][D]) / [A]
2. Ratio of forward/reverse reaction rates: 2.5
Discrepancy between the two values: 0 %
Reaction IS in equilibrium (within 1% tolerance)
True
bio.get_history()
| SYSTEM TIME | A | C | D | caption | |
|---|---|---|---|---|---|
| 0 | 0.00 | 4.000000 | 7.000000 | 2.000000 | Initial state |
| 1 | 0.20 | 5.600000 | 3.800000 | 0.400000 | |
| 2 | 0.25 | 4.352000 | 6.296000 | 1.648000 | |
| 3 | 0.30 | 4.301581 | 6.396838 | 1.698419 | |
| 4 | 0.35 | 4.312637 | 6.374726 | 1.687363 | |
| 5 | 0.40 | 4.310125 | 6.379749 | 1.689875 | |
| 6 | 0.45 | 4.310692 | 6.378617 | 1.689308 | |
| 7 | 0.50 | 4.310564 | 6.378872 | 1.689436 | |
| 8 | 0.55 | 4.310593 | 6.378815 | 1.689407 | |
| 9 | 0.60 | 4.310586 | 6.378828 | 1.689414 | |
| 10 | 0.65 | 4.310588 | 6.378825 | 1.689412 | |
| 11 | 0.70 | 4.310587 | 6.378825 | 1.689413 | |
| 12 | 0.75 | 4.310587 | 6.378825 | 1.689413 | |
| 13 | 0.80 | 4.310587 | 6.378825 | 1.689413 | |
| 14 | 0.85 | 4.310587 | 6.378825 | 1.689413 | |
| 15 | 0.90 | 4.310587 | 6.378825 | 1.689413 | |
| 16 | 0.95 | 4.310587 | 6.378825 | 1.689413 | |
| 17 | 1.00 | 4.310587 | 6.378825 | 1.689413 | |
| 18 | 1.05 | 4.310587 | 6.378825 | 1.689413 | |
| 19 | 1.10 | 4.310587 | 6.378825 | 1.689413 | |
| 20 | 1.15 | 4.310587 | 6.378825 | 1.689413 | |
| 21 | 1.20 | 4.310587 | 6.378825 | 1.689413 | |
| 22 | 1.25 | 4.310587 | 6.378825 | 1.689413 | |
| 23 | 1.30 | 4.310587 | 6.378825 | 1.689413 | |
| 24 | 1.35 | 4.310587 | 6.378825 | 1.689413 | |
| 25 | 1.40 | 4.310587 | 6.378825 | 1.689413 | |
| 26 | 1.45 | 4.310587 | 6.378825 | 1.689413 | |
| 27 | 1.50 | 4.310587 | 6.378825 | 1.689413 | |
| 28 | 1.55 | 4.310587 | 6.378825 | 1.689413 | |
| 29 | 1.60 | 4.310587 | 6.378825 | 1.689413 | |
| 30 | 1.65 | 4.310587 | 6.378825 | 1.689413 | |
| 31 | 1.70 | 4.310587 | 6.378825 | 1.689413 |
C and D get depleted, while A gets produced. A wild overshoot is present at t=0.2
fig = px.line(data_frame=bio.get_history(), x="SYSTEM TIME", y=["A", "C", "D"],
title="Reaction A <-> 2C + D . Changes in concentrations",
color_discrete_sequence = ['navy', 'violet', 'red'],
labels={"value":"concentration", "variable":"Chemical"})
fig.show()
Variable, adaptive time steps are explored at length in the "reactions_single_compartment" experiments