🚰 Interactive hydrodynamic solver for pipe and channel networks
View the Project on GitHub mdbartos/pipedream
This tutorial demonstrates how to use the pipedream solver to simulate the flow of water on a simple hillslope.
import numpy as np
import pandas as pd
from pipedream_solver.hydraulics import SuperLink
Model structure can be saved to or loaded from CSV files. In this case, our model consists of a set of superjunctions and a set of superlinks.
input_path = '../data/hillslope'
superjunctions = pd.read_csv(f'{input_path}/hillslope_superjunctions.csv')
superlinks = pd.read_csv(f'{input_path}/hillslope_superlinks.csv')
Superjunctions are basic finite volumes, and may represent manholes, retention ponds, or other bodies of water.
superjunctions
name | id | z_inv | h_0 | bc | storage | a | b | c | max_depth | map_x | map_y | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 0.00001 | False | functional | 0.0 | 0.0 | 200.0 | inf | 0 | 0 |
1 | 1 | 1 | 0 | 0.00001 | False | functional | 0.0 | 0.0 | 1000.0 | inf | 1 | 1 |
Superlinks are sections of channel or conduit that connect superjunctions together. Each superlink consists of a number of internal junctions and nodes connected in a linear fashion. In this case, we have a single superlink that connects the uphill superjunction to the downhill superjunction.
superlinks
name | id | sj_0 | sj_1 | in_offset | out_offset | dx | n | shape | g1 | g2 | g3 | g4 | Q_0 | h_0 | ctrl | A_s | A_c | C | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 1 | 0.0 | 0.0 | 1000 | 0.035 | rect_open | 10 | 5 | 0 | 0 | 0 | 0.00001 | False | 100 | 0 | 0 |
Internal links and junctions can be specified explicitly, or generated automatically inside each superlink. In this case, we will use 24 automatically-generated internal links.
internal_links = 24
The hydraulic model is instantiated with the SuperLink
class.
model = SuperLink(superlinks, superjunctions,
internal_links=internal_links)
Next, we specify the model parameters, including the default time step dt
, the inflow into each superjunction Q_in
, and the inflow into each internal junction Q_0Ik
.
dt = 10 # Model time step (s)
Q_in = 1e-3 * np.ones(model.M) # Flow into each internal junction (cms)
Q_0Ik = 1e-3 * np.ones(model.NIk) # Flow into each internal junction (cms)
Note that model.M
is the number of superjunctions, and model.NIk
is the number of internal junctions.
We can visualize the model with plot_profile
. Note that the hillslope at the start of the model run is dry.
# Plot profile from superjunctions 0 to 1 (uphill to downhill)
_ = model.plot_profile([0, 1], width=100)
Applying inflow to each superjunction and internal link causes water to flow down the hill.
# For each timestep...
for _ in range(4 * 360):
# Advance model forward in time
model.step(dt=dt, Q_in=Q_in, Q_0Ik=Q_0Ik)
_ = model.plot_profile([0, 1], width=100)
Ceasing the flow input and advancing the model in time causes the water to settle at the bottom of the hill.
for _ in range(3 * 360):
model.step(dt=dt)
_ = model.plot_profile([0, 1], width=100)