For a complete separation by means of membranes, see experiment membranes_3
LAST_REVISED = "Aug. 15, 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!
#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
from life123 import BioSim1D, ChemData, PlotlyHelper, check_version
check_version(LIFE123_VERSION)
OK
with identical bin concentrations of the chemicals A and B, in the center bin.
B diffuses much faster than A
chem_data = ChemData(names=["A", "B"], diffusion_rates=[0.1, 2.], plot_colors=["turquoise", "green"])
bio = BioSim1D(n_bins=9, chem_data=chem_data)
bio.set_bin_conc(bin_address=4, chem_label="A", conc=10.)
bio.set_bin_conc(bin_address=4, chem_label="B", conc=10.)
bio.describe_state()
SYSTEM STATE at Time t = 0: 9 bins and 2 chemical species
| Species | Diff rate | Bin 0 | Bin 1 | Bin 2 | Bin 3 | Bin 4 | Bin 5 | Bin 6 | Bin 7 | Bin 8 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A | 0.1 | 0.0 | 0.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 1 | B | 2.0 | 0.0 | 0.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 | 0.0 | 0.0 |
bio.system_snapshot()
| A | B | |
|---|---|---|
| 0 | 0.0 | 0.0 |
| 1 | 0.0 | 0.0 |
| 2 | 0.0 | 0.0 |
| 3 | 0.0 | 0.0 |
| 4 | 10.0 | 10.0 |
| 5 | 0.0 | 0.0 |
| 6 | 0.0 | 0.0 |
| 7 | 0.0 | 0.0 |
| 8 | 0.0 | 0.0 |
bio.visualize_system(title_prefix="Diffusion. The 2 concentrations initially perfectly overlap") # Line curve view
bio.system_heatmaps(title_prefix="Diffusion")
# Request to save the concentration history at the bin with the initial concentration injection,
# and at a couple of other bins
bio.enable_history(bins=[0, 2, 4], frequency=3, take_snapshot=True)
History enabled for bins [0, 2, 4], for ALL chemicals
# Advancing to time t=1, with moderate time steps
bio.diffuse(total_duration=1.0, fraction_max_step=0.4)
{'steps': 16, 'system time': '1.0667', 'time_step': 0.066666}
bio.describe_state()
SYSTEM STATE at Time t = 1.066656: 9 bins and 2 chemical species
| Species | Diff rate | Bin 0 | Bin 1 | Bin 2 | Bin 3 | Bin 4 | Bin 5 | Bin 6 | Bin 7 | Bin 8 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A | 0.1 | 0.000031 | 0.001396 | 0.044318 | 0.876317 | 8.155875 | 0.876317 | 0.044318 | 0.001396 | 0.000031 |
| 1 | B | 2.0 | 0.397538 | 0.694625 | 1.209567 | 1.725287 | 1.945964 | 1.725287 | 1.209567 | 0.694625 | 0.397538 |
A and B, previously identical in concentrations, have separated due to their different diffusion rates¶Notice how B has spread out far more than A
bio.visualize_system(title_prefix="Diffusion") # Line curve view
bio.system_heatmaps(title_prefix="Diffusion")
bio.diffuse(total_duration=2.0, fraction_max_step=0.4)
{'steps': 31, 'system time': '3.1333', 'time_step': 0.066666}
bio.describe_state()
SYSTEM STATE at Time t = 3.133302: 9 bins and 2 chemical species
| Species | Diff rate | Bin 0 | Bin 1 | Bin 2 | Bin 3 | Bin 4 | Bin 5 | Bin 6 | Bin 7 | Bin 8 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A | 0.1 | 0.002127 | 0.027200 | 0.270603 | 1.770845 | 5.858450 | 1.770845 | 0.270603 | 0.027200 | 0.002127 |
| 1 | B | 2.0 | 1.009997 | 1.057293 | 1.129782 | 1.193555 | 1.218748 | 1.193555 | 1.129782 | 1.057293 | 1.009997 |
B is close to equilibrium, while A is nowhere near it!¶bio.visualize_system(title_prefix="Diffusion") # Line curve view
bio.system_heatmaps(title_prefix="Diffusion")
bio.diffuse(total_duration=2.0, fraction_max_step=0.4)
{'steps': 31, 'system time': '5.1999', 'time_step': 0.066666}
bio.describe_state()
SYSTEM STATE at Time t = 5.199948: 9 bins and 2 chemical species
| Species | Diff rate | Bin 0 | Bin 1 | Bin 2 | Bin 3 | Bin 4 | Bin 5 | Bin 6 | Bin 7 | Bin 8 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A | 0.1 | 0.012045 | 0.087799 | 0.524250 | 2.107562 | 4.536688 | 2.107562 | 0.524250 | 0.087799 | 0.012045 |
| 1 | B | 2.0 | 1.097383 | 1.103807 | 1.113648 | 1.122302 | 1.125720 | 1.122302 | 1.113648 | 1.103807 | 1.097383 |
A and B in the central bin 4 are again getting closer in value¶bio.visualize_system(title_prefix="Diffusion") # Line curve view
bio.system_heatmaps(title_prefix="Diffusion")
bio.diffuse(total_duration=95.0, fraction_max_step=0.4)
{'steps': 1426, 'system time': '100.27', 'time_step': 0.066666}
bio.describe_state()
SYSTEM STATE at Time t = 100.26566: 9 bins and 2 chemical species
| Species | Diff rate | Bin 0 | Bin 1 | Bin 2 | Bin 3 | Bin 4 | Bin 5 | Bin 6 | Bin 7 | Bin 8 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A | 0.1 | 1.092097 | 1.100994 | 1.114625 | 1.126612 | 1.131346 | 1.126612 | 1.114625 | 1.100994 | 1.092097 |
| 1 | B | 2.0 | 1.111111 | 1.111111 | 1.111111 | 1.111111 | 1.111111 | 1.111111 | 1.111111 | 1.111111 | 1.111111 |
bio.visualize_system(title_prefix="Diffusion") # Line curve view
bio.system_heatmaps(title_prefix="Diffusion")
# Let's verify mass conservation
bio.check_mass_conservation(chem_label="A", expected=10.)
True
bio.check_mass_conservation(chem_label="B", expected=10.)
True
A and B at selected bins (bins whose history-keeping we requested prior to running the simulation)¶bin4_hist = bio.conc_history.bin_history(bin_address=4) # The bin where the initial concentration of `A` and `B` was applied
bin4_hist
| SYSTEM TIME | A | B | |
|---|---|---|---|
| 0 | 0.000000 | 10.000000 | 10.000000 |
| 1 | 0.199998 | 9.607945 | 4.725956 |
| 2 | 0.399996 | 9.238843 | 3.251818 |
| 3 | 0.599994 | 8.891203 | 2.617687 |
| 4 | 0.799992 | 8.563635 | 2.254197 |
| ... | ... | ... | ... |
| 496 | 99.399006 | 1.132184 | 1.111111 |
| 497 | 99.599004 | 1.131988 | 1.111111 |
| 498 | 99.799002 | 1.131793 | 1.111111 |
| 499 | 99.999000 | 1.131600 | 1.111111 |
| 500 | 100.198998 | 1.131409 | 1.111111 |
501 rows × 3 columns
bio.plot_history_single_bin(bin_address=4, title_prefix="`A` and `B` separate, until they finally rejoin")
A and B is best seen by plotting the difference of their concentrations, as a function of time¶bin4_hist["A"] - bin4_hist["B"]
0 0.000000
1 4.881988
2 5.987024
3 6.273516
4 6.309437
...
496 0.021073
497 0.020877
498 0.020682
499 0.020489
500 0.020298
Length: 501, dtype: float64
PlotlyHelper.plot_curves(x=bin4_hist['SYSTEM TIME'], y = bin4_hist['A'] - bin4_hist['B'],
x_label="SYSTEM TIME", y_label="[A] - [B]",
colors="purple", title="Transient separation of `A` and `B`, as seen in central bin 4")
A and B is also seen in other bins...¶bio.plot_history_single_bin(bin_address=0, title_prefix="The transient separation of `A` and `B` happens at other bins, too...")
bio.plot_history_single_bin(bin_address=2, title_prefix="The transient separation of `A` and `B` happens at other bins, too...")