LAST_REVISED = "Jan. 20, 2025"
LIFE123_VERSION = "1.0.0rc2" # 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 BioSim2D, ChemData, check_version
check_version(LIFE123_VERSION)
OK
# Prepare the initial system, with two concentration pulses, at almost-opposite ends of the system, with the same diffusion rate coefficient
chem_data = ChemData(names=["A", "B"], diffusion_rates=[0.05, 0.05])
bio = BioSim2D(x_bins=7, y_bins=10, chem_data=chem_data) # 3 more rows, compared to experiment `diffusion_2_a`
bio.set_bin_conc(bin_address = (1,1), chem_label="A", conc=10.)
bio.set_bin_conc(bin_address = (5,5), chem_label="B", conc=10.)
Notice the bin with the initial concentration of A and the other bin with the initial concentration of B
bio.describe_state()
SYSTEM STATE at Time t = 0:
Species `A`:
0 1 2 3 4 5 6
9 0.0 0.0 0.0 0.0 0.0 0.0 0.0
8 0.0 0.0 0.0 0.0 0.0 0.0 0.0
7 0.0 0.0 0.0 0.0 0.0 0.0 0.0
6 0.0 0.0 0.0 0.0 0.0 0.0 0.0
5 0.0 0.0 0.0 0.0 0.0 0.0 0.0
4 0.0 0.0 0.0 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1 0.0 10.0 0.0 0.0 0.0 0.0 0.0
0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Species `B`:
0 1 2 3 4 5 6
9 0.0 0.0 0.0 0.0 0.0 0.0 0.0
8 0.0 0.0 0.0 0.0 0.0 0.0 0.0
7 0.0 0.0 0.0 0.0 0.0 0.0 0.0
6 0.0 0.0 0.0 0.0 0.0 0.0 0.0
5 0.0 0.0 0.0 0.0 0.0 10.0 0.0
4 0.0 0.0 0.0 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0 0.0 0.0 0.0
2 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
bio.system_snapshot(chem_label="A")
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
|---|---|---|---|---|---|---|---|
| 9 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 8 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 7 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 6 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 5 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 4 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 1 | 0.0 | 10.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
bio.system_snapshot(chem_label="B")
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
|---|---|---|---|---|---|---|---|
| 9 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 8 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 7 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 6 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 5 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 10.0 | 0.0 |
| 4 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 1 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
bio.system_heatmaps()
Notice that the bins with the initial concentration pulses lie on a diagonal from each other, but one is closer to the system "walls"
# Request to save the concentration history of all chemicals at selected bins
bio.enable_history(bins=[(1,1), (3,3), (1,6)], frequency=5, take_snapshot=True) # Taking a snapshot to include the current initial state in the history
History enabled for bins [(1, 1), (3, 3), (1, 6)] and chemicals None (None means 'all')
delta_time = 2.5
status = bio.diffuse(total_duration=delta_time, time_step=0.1)
print("\n", status)
bio.system_heatmaps(title_prefix="Diffusion")
{'steps': 25}
# MASS-CONSERVATION CHECK. Verify that that sum of all the entries in each of the above matrices is still the initial 10.
bio.check_mass_conservation(chem_label="A", expected=10.) \
and \
bio.check_mass_conservation(chem_label="B", expected=10.)
True
status = bio.diffuse(total_duration=delta_time, time_step=0.1)
print("\n", status)
bio.system_heatmaps(title_prefix="Diffusion")
{'steps': 25}
for i in range(300):
status = bio.diffuse(total_duration=delta_time, time_step=0.2)
if i==3 or i==20 or i==50 or i==100 or i==299:
fig = bio.system_heatmaps(title_prefix="Diffusion")
fig.show()
Notice how B, further away from walls compared to A, has an opportunity to spread out more quickly, in spite of the same diffusion rate coefficient
Mass conservations: the initial "10. units of concentration" are now uniformly spread across the 70 (7x10) bins, leading to a near-constant concentration of 10./60
10./70
0.14285714285714285
# Mass conservation for both `A` and `B` can also be verified as follows:
bio.check_mass_conservation(chem_label="A", expected=10.)
True
bio.check_mass_conservation(chem_label="B", expected=10.)
True
bio.plot_history_single_bin(bin_address=(1,1)) # The bin with the initial pulse of `A`
bio.plot_history_single_bin(bin_address=(3,3)) # The bin halfway between the initial pulses of `A` and `B`
Even thought bin (3,3) is exactly halfway between the bins with the initial pulses of A and B, an asymmetry develops because A is more "hemmed in by walls", and has fewer directions to spread out, including towards (3,3), while B also dilutes away towards the top (high y-bin values) of the system. Thus A arrives more quickly.
(Compare to the perfect overlap in experiment diffusion_2_a)
bio.plot_history_single_bin(bin_address=((1, 6))) # Distance from (1,1), with the initial pulse of `A`, is 5;
# distance from (5,5), with the initial pulse of `B`, is 4.12
B arrives more quickly at this bin, until A eventually catches up