A <-> B,¶with 1st-order kinetics in both directions, taken to equilibrium.
Same as experiment react_1_a, but with CSV file storage of the concentration history, and reaction stop-restart.
LAST_REVISED = "Aug. 29, 2025"
LIFE123_VERSION = "1.0.0rc6" # Library version this experiment is based on
#import set_path # Using MyBinder? Uncomment this before running the next cell!
# Importing this module will add the project's home directory to sys.path
#import sys
#sys.path.append("C:/some_path/my_env_or_install") # CHANGE to the folder containing your venv or libraries installation!
# NOTE: If any of the imports below can't find a module, uncomment the lines above, or try: import set_path
import ipynbname
import life123
life123.check_version(LIFE123_VERSION) # To check compatibility
OK
# Initialize logging (for the system state)
csv_log_file = ipynbname.name() + "_system_log.csv" # Use the notebook base filename
# IN CASE OF PROBLEMS, set manually to any desired name
# Instantiate the simulator and specify the chemicals
uc = life123.UniformCompartment()
# We're now requesting that all System Concentration Data get logged in our previously-specified CSV file
uc.start_csv_log(csv_log_file)
-> CSV-format output will be LOGGED into the file 'react_1_b_system_log.csv' . An existing file by that name was over-written
# Reaction A <-> B , with 1st-order kinetics in both directions
uc.add_reaction(reactants="A", products="B", kF=3., kR=2.)
uc.describe_reactions()
Number of reactions: 1 0: A <-> B (Elementary Unimolecular reaction) (kF = 3 / kR = 2 / delta_G = -1,005.1 / K = 1.5 / Temp = 25 C) Chemicals involved in the above reactions: ['A', 'B']
# Set the initial concentrations of all the chemicals
uc.set_conc({"A": 80., "B": 10.})
react_1_a) we'll be running the simulation in two parts¶
uc.single_compartment_react(initial_step=0.1, target_end_time=0.2) # The first part of our run
28 total variable step(s) taken in 0.00 min
Number of step re-do's because of elective soft aborts: 3
Norm usage: {'norm_A': 12, 'norm_B': 8, 'norm_C': 8, 'norm_D': 8}
System Time is now: 0.2117
uc.get_history() # The system's concentrations history, saved during the run of single_compartment_react()
| SYSTEM TIME | A | B | step | caption | |
|---|---|---|---|---|---|
| 0 | 0.000000 | 80.000000 | 10.000000 | Set concentration | |
| 1 | 0.006400 | 78.592000 | 11.408000 | 1 | 1st reaction step |
| 2 | 0.009600 | 77.910528 | 12.089472 | 2 | |
| 3 | 0.013440 | 77.105846 | 12.894154 | 3 | |
| 4 | 0.018048 | 76.158767 | 13.841233 | 4 | |
| 5 | 0.023578 | 75.048458 | 14.951542 | 5 | |
| 6 | 0.029107 | 73.968846 | 16.031154 | 6 | |
| 7 | 0.034637 | 72.919083 | 17.080917 | 7 | |
| 8 | 0.040166 | 71.898344 | 18.101656 | 8 | |
| 9 | 0.045696 | 70.905827 | 19.094173 | 9 | |
| 10 | 0.052332 | 69.747735 | 20.252265 | 10 | |
| 11 | 0.058967 | 68.628067 | 21.371933 | 11 | |
| 12 | 0.065603 | 67.545546 | 22.454454 | 12 | |
| 13 | 0.072238 | 66.498940 | 23.501060 | 13 | |
| 14 | 0.078874 | 65.487058 | 24.512942 | 14 | |
| 15 | 0.085509 | 64.508749 | 25.491251 | 15 | |
| 16 | 0.093472 | 63.373726 | 26.626274 | 16 | |
| 17 | 0.101434 | 62.283893 | 27.716107 | 17 | |
| 18 | 0.109397 | 61.237449 | 28.762551 | 18 | |
| 19 | 0.117360 | 60.232668 | 29.767332 | 19 | |
| 20 | 0.125322 | 59.267889 | 30.732111 | 20 | |
| 21 | 0.134877 | 58.156249 | 31.843751 | 21 | |
| 22 | 0.144433 | 57.097717 | 32.902283 | 22 | |
| 23 | 0.153988 | 56.089758 | 33.910242 | 23 | |
| 24 | 0.163543 | 55.129955 | 34.870045 | 24 | |
| 25 | 0.175009 | 54.033218 | 35.966782 | 25 | |
| 26 | 0.186475 | 52.999357 | 37.000643 | 26 | |
| 27 | 0.197941 | 52.024769 | 37.975231 | 27 | |
| 28 | 0.211701 | 50.922312 | 39.077688 | 28 | last reaction step |
uc.plot_history(show_intervals=True)
# We're nowhere near equilibrium yet!
uc.is_in_equilibrium()
0: A <-> B
Current concentrations: [A] = 50.92 ; [B] = 39.08
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 0.767398
Formula used: [B] / [A]
2. Ratio of forward/reverse reaction rates: 1.5
Discrepancy between the two values: 48.84 %
Reaction is NOT in equilibrium (not within 1% tolerance)
{False: [0]}
initial_step = 0.013759414272 # We're choosing this value simply FOR DEMONSTRATION PURPOSES,
# to remain in exact lockstep with the time course of experiment `react_1_a`
'''
If you run experiment `react_1_a`, you can determine what the next time step would have been, had we not stopped early this time.
In experiment `react_1_a`, after running the simulation, you can issue:
list(uc.get_history(t_start=0.21, t_end=0.23, columns="SYSTEM TIME"))
and you will get: [0.211700785152, 0.225460199424]
Their difference is the initial_step we're using here.
''';
uc.single_compartment_react(initial_step=0.013759414272, target_end_time=1.0) # The 2nd part of our run, to the final target end time
19 total variable step(s) taken in 0.00 min
Norm usage: {'norm_A': 14, 'norm_B': 14, 'norm_C': 14, 'norm_D': 14}
System Time is now: 1.1343
uc.get_history() # The cumulative system's history
| SYSTEM TIME | A | B | step | caption | |
|---|---|---|---|---|---|
| 0 | 0.000000 | 80.000000 | 10.000000 | Set concentration | |
| 1 | 0.006400 | 78.592000 | 11.408000 | 1 | 1st reaction step |
| 2 | 0.009600 | 77.910528 | 12.089472 | 2 | |
| 3 | 0.013440 | 77.105846 | 12.894154 | 3 | |
| 4 | 0.018048 | 76.158767 | 13.841233 | 4 | |
| 5 | 0.023578 | 75.048458 | 14.951542 | 5 | |
| 6 | 0.029107 | 73.968846 | 16.031154 | 6 | |
| 7 | 0.034637 | 72.919083 | 17.080917 | 7 | |
| 8 | 0.040166 | 71.898344 | 18.101656 | 8 | |
| 9 | 0.045696 | 70.905827 | 19.094173 | 9 | |
| 10 | 0.052332 | 69.747735 | 20.252265 | 10 | |
| 11 | 0.058967 | 68.628067 | 21.371933 | 11 | |
| 12 | 0.065603 | 67.545546 | 22.454454 | 12 | |
| 13 | 0.072238 | 66.498940 | 23.501060 | 13 | |
| 14 | 0.078874 | 65.487058 | 24.512942 | 14 | |
| 15 | 0.085509 | 64.508749 | 25.491251 | 15 | |
| 16 | 0.093472 | 63.373726 | 26.626274 | 16 | |
| 17 | 0.101434 | 62.283893 | 27.716107 | 17 | |
| 18 | 0.109397 | 61.237449 | 28.762551 | 18 | |
| 19 | 0.117360 | 60.232668 | 29.767332 | 19 | |
| 20 | 0.125322 | 59.267889 | 30.732111 | 20 | |
| 21 | 0.134877 | 58.156249 | 31.843751 | 21 | |
| 22 | 0.144433 | 57.097717 | 32.902283 | 22 | |
| 23 | 0.153988 | 56.089758 | 33.910242 | 23 | |
| 24 | 0.163543 | 55.129955 | 34.870045 | 24 | |
| 25 | 0.175009 | 54.033218 | 35.966782 | 25 | |
| 26 | 0.186475 | 52.999357 | 37.000643 | 26 | |
| 27 | 0.197941 | 52.024769 | 37.975231 | 27 | |
| 28 | 0.211701 | 50.922312 | 39.077688 | 28 | last reaction step |
| 29 | 0.225460 | 49.895700 | 40.104300 | 1 | 1st reaction step |
| 30 | 0.239220 | 48.939717 | 41.060283 | 2 | |
| 31 | 0.255731 | 47.871459 | 42.128541 | 3 | |
| 32 | 0.272242 | 46.891393 | 43.108607 | 4 | |
| 33 | 0.292056 | 45.812407 | 44.187593 | 5 | |
| 34 | 0.311869 | 44.840314 | 45.159686 | 6 | |
| 35 | 0.335646 | 43.789365 | 46.210635 | 7 | |
| 36 | 0.359422 | 42.863355 | 47.136645 | 8 | |
| 37 | 0.387953 | 41.884245 | 48.115755 | 9 | |
| 38 | 0.422191 | 40.876927 | 49.123073 | 10 | |
| 39 | 0.456429 | 40.042050 | 49.957950 | 11 | |
| 40 | 0.497514 | 39.211704 | 50.788296 | 12 | |
| 41 | 0.546817 | 38.419979 | 51.580021 | 13 | |
| 42 | 0.605980 | 37.704113 | 52.295887 | 14 | |
| 43 | 0.676975 | 37.099191 | 52.900809 | 15 | |
| 44 | 0.762170 | 36.630965 | 53.369035 | 16 | |
| 45 | 0.864404 | 36.308436 | 53.691564 | 17 | |
| 46 | 0.987084 | 36.119241 | 53.880759 | 18 | |
| 47 | 1.134300 | 36.031470 | 53.968530 | 19 | last reaction step |
uc.plot_history(show_intervals=True)
# Verify that the reaction has reached equilibrium
uc.is_in_equilibrium()
0: A <-> B
Current concentrations: [A] = 36.03 ; [B] = 53.97
1. Ratio of reactant/product concentrations, adjusted for reaction orders: 1.49782
Formula used: [B] / [A]
2. Ratio of forward/reverse reaction rates: 1.5
Discrepancy between the two values: 0.1456 %
Reaction IS in equilibrium (within 1% tolerance)
True
csv_log_file
'react_1_b_system_log.csv'
# Here's dump of the contents of that log file
with open(csv_log_file, 'r', encoding='utf8') as fh:
file_contents = fh.read()
print(file_contents)
SYSTEM TIME,A,B,step,caption 0.0,80.0,10.0,,Set concentration 0.006400000000000002,78.592,11.408000000000001,1,1st reaction step 0.009600000000000003,77.910528,12.089472,2, 0.013440000000000004,77.1058458624,12.894154137600001,3, 0.018048000000000005,76.15876717373031,13.841232826269698,4, 0.023577600000000004,75.04845757891101,14.951542421088993,5, 0.029107200000000007,73.96884582376929,16.031154176230725,6, 0.03463680000000001,72.91908317443371,17.080916825566298,7, 0.04016640000000001,71.89834436282696,18.101655637173042,8, 0.045696000000000014,70.90582693788352,19.094173062116482,9, 0.05233152000000001,69.7477353740692,20.252264625930806,10, 0.05896704000000001,68.62806650892247,21.371933491077524,11, 0.06560256000000002,67.54554556951605,22.45445443048395,12, 0.07223808000000002,66.49894007682887,23.501059923171127,13, 0.07887360000000003,65.48705844253587,24.512941557464124,14, 0.08550912000000004,64.50874861235279,25.491251387647203,15, 0.09347174400000004,63.373726382799354,26.62627361720064,16, 0.10143436800000004,62.2838929294738,27.716107070526196,17, 0.10939699200000004,61.237449146205506,28.762550853794487,18, 0.11735961600000004,60.23266755485373,29.767332445146263,19, 0.12532224000000003,59.26788945357223,30.732110546427762,20, 0.13487738880000003,58.15624872361806,31.84375127638193,21, 0.14443253760000002,57.09771745659816,32.90228254340183,22, 0.15398768640000002,56.0897583084074,33.910241691592596,23, 0.16354283520000001,55.12995515844305,34.87004484155694,24, 0.17500901376000003,54.033217749985546,35.96678225001445,25, 0.18647519232000004,52.999357276322066,37.00064272367793,26, 0.19794137088000005,52.02476894664434,37.97523105335565,27, 0.21170078515200005,50.92231177389454,39.07768822610545,28, 0.22546019942400006,49.89570042592975,40.10429957407024,1,1st reaction step 0.23921961369600006,48.93971693212988,41.06028306787011,2, 0.25573091082240007,47.871459377140354,42.12854062285964,3, 0.27224220794880005,46.89139341164059,43.1086065883594,4, 0.29205576450048004,45.81240721519991,44.18759278480008,5, 0.31186932105216003,44.84031378886753,45.15968621113246,6, 0.335645588914176,43.78936544572559,46.2106345542744,7, 0.359421856776192,42.863355249162076,47.13664475083792,8, 0.38795337821061116,41.88424541214457,48.11575458785542,9, 0.42219120393191417,40.87692656753266,49.123073432467336,10, 0.4564290296532172,40.042049758158775,49.95795024184122,11, 0.4975144205187808,39.21170378709872,50.78829621290127,12, 0.5468168895574572,38.41997915447455,51.580020845525446,13, 0.6059798524038689,37.704113470448206,52.29588652955179,14, 0.6769754078195629,37.099191058819024,52.90080894118097,15, 0.7621700743183957,36.630964980446095,53.3690350195539,16, 0.8644036741169949,36.30843587395681,53.69156412604318,17, 0.9870839938753141,36.11924081574702,53.88075918425297,18, 1.1343003775852971,36.031469807322495,53.9685301926775,19,