Bathtub Fill and Drain
A bathtub simulation illustrating stock and flow of water volume.
Level:Beginner
Stocks and Flows
Learn about the foundational concepts of Stocks and Flows in systems thinking and how they interact to create system behavior.
Explore Stocks and Flowssimulation.py
Filling and emptying a bathtub
This pared‑down example highlights the essence of stocks and flows. Water pours in from the tap while some trickles down the drain. By keeping things simple we can watch how the water level changes from one minute to the next.
from tys import probe, progress
Simulate water level in a tub with inflow and drain.
def simulate(cfg: dict):
import simpy
env = simpy.Environment()
volume = cfg["initial_volume"] # water in tub (liters)
inflow = cfg["inflow_rate"] # liters per minute entering
drain = cfg["drain_rate"] # liters per minute leaving
minutes = cfg["minutes"]
done = env.event()
Update the water volume each minute.
def run():
nonlocal volume
for m in range(minutes):
volume += inflow - drain
volume = max(0, volume)
probe("water_volume", env.now, volume)
probe("inflow", env.now, inflow)
probe("outflow", env.now, drain)
progress(int(100 * (m + 1) / minutes))
yield env.timeout(1)
done.succeed({"final_volume": volume})
env.process(run())
env.run(until=done)
return done.value
def requirements():
return {
"builtin": ["micropip", "pyyaml"],
"external": ["simpy==4.1.1"],
}
Default.yaml
initial_volume: 0
inflow_rate: 8
drain_rate: 3
minutes: 20
Charts (Default)
Final Results (Default)
Metric | Value |
---|---|
final_volume | 100.00 |
FAQ
- How is the water volume updated each minute?
- Volume increases by inflow and decreases by the drain rate while never dropping below zero.
- What prevents negative volume when the drain exceeds inflow?
- The simulation clamps volume to at least zero after each update.
- Where do the probe values come from?
- The run process emits water_volume, inflow and outflow every minute so the charts show how they change.