PyFlo¶
By: Amulya Nagella¶
This is a python package that can be used for estimating runoff rates, rainfall/runoff storage over time, and flood routing analyses. The tutorial below will take you through the process of generating a hydrograph using 2 different methods: Soil Conservation Service (SCS) Method and the Rational Method.
The hydrograph will represent the time-flow relationship per unit of runoff or rainfall depth.
Rainfall: amount of precipitation that falls into a specifc area (usually in the form of rain)
Runoff: precipitation that flows over watersheds (does not infiltrate into soil or vegetation) and flows off into water bodies (streams, lakes, or rivers).
Package Installation¶
# conda install -c conda-forge pyflo
# mamba install -c conda-forge pyflo
# pip install pyflo
Import Packages¶
from pyflo import system
from pyflo.nrcs import hydrology
import xarray as xr
from matplotlib import pyplot as plt
import cartopy.crs as ccrs
import cartopy
import cartopy.feature as cfeature
import pandas as pd
import numpy as np
Method 1: SCS (or NRCS) Equation¶
This method is suitable for a wide range of watershed sizes and land uses (rural and urban areas). Generally preferred for longer-duration storms.
Unit Hydrograph¶
Represents the direct runoff from a unit depth (usually 1 inch) of rainfall over a watershed during a short-duration rainfall event.
Required Parameters:¶
area = the region that the water is flowing into, size of the basin.
cn = runoff coefficient, indicating the intensity of the runoff amount (rainfall volume).
tc = time of concentration, amount of time it takes the runoff volume to travel from the most remote location within the watershed into the outlet of the watershed.
runoff distribution = unscaled unit hydrograph runoff distribution.
peak_factor = scaling of the peak factor (depending on the conditions of the area).
# Define the runoff distribution
runoff_distribution = system.array_from_csv('/home/an691/rcaes/runoff_d1.csv')
runoff_distribution
array([[0. , 0. ], [0.1 , 0.03 ], [0.2 , 0.1 ], [0.3 , 0.19 ], [0.4 , 0.31 ], [0.5 , 0.47 ], [0.6 , 0.66 ], [0.7 , 0.82 ], [0.8 , 0.93 ], [0.9 , 0.99 ], [1. , 1. ], [1.1 , 0.99 ], [1.2 , 0.93 ], [1.3 , 0.86 ], [1.4 , 0.78 ], [1.5 , 0.68 ], [1.6 , 0.56 ], [1.7 , 0.46 ], [1.8 , 0.39 ], [1.9 , 0.33 ], [2. , 0.28 ], [2.2 , 0.207], [2.4 , 0.147], [2.6 , 0.107], [2.8 , 0.077], [3. , 0.055], [3.2 , 0.04 ], [3.4 , 0.029], [3.6 , 0.021], [3.8 , 0.015], [4. , 0.011], [4.5 , 0.005], [5. , 0. ]])
# Define the Pre-development Basin - SCS
pre_scs_basin = hydrology.Basin(
area=132,
cn=69.0,
tc=1.0,
runoff_dist=runoff_distribution,
peak_factor=1.0)
pre_scs_unit_hydrograph = pre_scs_basin.unit_hydrograph(interval=0.3)
# Define the Post-development Basin - SCS
post_scs_basin = hydrology.Basin(
area=132,
cn=90.0,
tc=1.0,
runoff_dist=runoff_distribution,
peak_factor=2.0)
post_scs_unit_hydrograph = post_scs_basin.unit_hydrograph(interval=0.3)
fig, axes = plt.subplots(ncols=2, figsize=(10,4))
ax0, ax1 = axes
#Pre-development Hydrograph
x_pre = pre_scs_unit_hydrograph[:, 0]
y_pre = pre_scs_unit_hydrograph[:, 1]
ax0.plot(x_pre, y_pre, 'k')
ax0.plot(x_pre, y_pre, 'bo')
ax0.set_title(r'Pre-development Unit Hydrograph (SCS)')
ax0.set_xlabel(r'Time ($hr$)')
ax0.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Pre-development Hydrograph
x_post = post_scs_unit_hydrograph[:, 0]
y_post = post_scs_unit_hydrograph[:, 1]
ax1.plot(x_post, y_post, 'k')
ax1.plot(x_post, y_post, 'bo')
ax1.set_title(r'Post-development Unit Hydrograph (SCS)')
ax1.set_xlabel(r'Time ($hr$)')
ax1.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
plt.tight_layout()
Flood Hydrograph¶
Represents the discharge of a waer bodie over time in response to a specific rainfall event oer a longer duration.
#Define Rainfall Distribution intensity over a 1 hour duration
rainfall_dist = np.array([
(0.00, 0.000),
(0.05, 0.074),
(0.10, 0.174),
(0.15, 0.280),
(0.20, 0.378),
(0.25, 0.448),
(0.30, 0.496),
(0.35, 0.526),
(0.40, 0.540),
(0.45, 0.540),
(0.50, 0.540),
(0.55, 0.542),
(0.60, 0.554),
(0.65, 0.582),
(0.70, 0.640),
(0.75, 0.724),
(0.80, 0.816),
(0.85, 0.886),
(0.90, 0.940),
(0.95, 0.980),
(1.00, 1.000)
])
rainfall_depths1 = rainfall_dist * [6.0, 5.0] # Scale array to 5 inches over 6 hours.
rainfall_depths2 = rainfall_dist * [6.0, 12.0] # Scale array to 12 inches over 6 hours.
pre_flood_hydrograph = pre_scs_basin.flood_hydrograph(rainfall_depths1, interval=0.3)
post_flood_hydrograph = post_scs_basin.flood_hydrograph(rainfall_depths1, interval=0.3)
pre_flood_hydrograph2 = pre_scs_basin.flood_hydrograph(rainfall_depths2, interval=0.3)
post_flood_hydrograph2 = post_scs_basin.flood_hydrograph(rainfall_depths2, interval=0.3)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10,6))
ax0, ax1, ax2, ax3 = axes.flatten()
#Pre-development Hydrograph
x_pre_flood = pre_flood_hydrograph[:, 0]
y_pre_flood = pre_flood_hydrograph[:, 1]
ax0.plot(x_pre_flood, y_pre_flood, 'k')
ax0.plot(x_pre_flood, y_pre_flood, 'bo')
ax0.set_title(r'Pre-development, 5 in')
ax0.set_xlabel(r'Time ($hr$)')
ax0.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Pre-development Hydrograph
x_post_flood = post_flood_hydrograph[:, 0]
y_post_flood = post_flood_hydrograph[:, 1]
ax1.plot(x_post_flood, y_post_flood, 'k')
ax1.plot(x_post_flood, y_post_flood, 'bo')
ax1.set_title(r'Post-development, 5 in')
ax1.set_xlabel(r'Time ($hr$)')
ax1.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Pre-development Hydrograph
x_pre_flood = pre_flood_hydrograph2[:, 0]
y_pre_flood = pre_flood_hydrograph2[:, 1]
ax2.plot(x_pre_flood, y_pre_flood, 'k')
ax2.plot(x_pre_flood, y_pre_flood, 'bo')
ax2.set_title(r'Pre-development, 12 in')
ax2.set_xlabel(r'Time ($hr$)')
ax2.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Pre-development Hydrograph
x_post_flood = post_flood_hydrograph2[:, 0]
y_post_flood = post_flood_hydrograph2[:, 1]
ax3.plot(x_post_flood, y_post_flood, 'k')
ax3.plot(x_post_flood, y_post_flood, 'bo')
ax3.set_title(r'Post-development, 12 in')
ax3.set_xlabel(r'Time ($hr$)')
ax3.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Adding a title to all subplots
plt.suptitle("NRCS (SCS) Method Flood Hydrographs")
plt.tight_layout()
plt.show()
Method 2: Rational Equation¶
This method is mainly used for small urban or suburban watersheds and is best suited for short-duration storms. It assumes a uniform rainfall intensity across the watershed during the storm.
Flood Hydrograph¶
Represents the discharge of a water bodies over time in response to a specific rainfall event over a longer duration.
Required Parameters:¶
area = the region that the water is flowing into, size of the basin.
c = runoff coefficient, ratio value between 0-1.
tc = time of concentration, amount of time it takes the runoff volume to travel from the most remote location within the watershed into the outlet of the watershed.
from pyflo.rational import hydrology
# Define the Pre-development Basin - Rational
pre_rat_basin = hydrology.Basin(
area=132,
c=0.15,
tc=1.0)
# Define the Post-development Basin - Rational
post_rat_basin = hydrology.Basin(
area=132,
c=0.70,
tc=1.0)
# Define Rainfall Distribution
rainfall_dist = np.array([
(0.01, 0.0001),
(0.05, 0.1),
(0.10, 0.2),
(0.15, 0.3),
(0.20, 0.4),
(0.25, 0.5),
(0.30, 0.6),
(0.35, 0.7),
(0.40, 0.8),
(0.45, 0.9),
(0.50, 1.0),
(0.55, 0.9),
(0.60, 0.8),
(0.65, 0.7),
(0.70, 0.6),
(0.75, 0.5),
(0.80, 0.4),
(0.85, 0.3),
(0.90, 0.2),
(0.95, 0.1),
(1.00, 0.0001)
])
rainfall_depths1 = rainfall_dist * [6.0, 5.0] # Scale array to 5 inches over 6 hours.
rainfall_depths2 = rainfall_dist * [6.0, 12.0] # Scale array to 12 inches over 6 hours.
pre_rat_flood_hydrograph = pre_rat_basin.flood_hydrograph(rainfall_depths1, interval=0.1)
post_rat_flood_hydrograph = post_rat_basin.flood_hydrograph(rainfall_depths1, interval=0.3)
pre_rat_flood_hydrograph2 = pre_rat_basin.flood_hydrograph(rainfall_depths2, interval=0.3)
post_rat_flood_hydrograph2 = post_rat_basin.flood_hydrograph(rainfall_depths2, interval=0.3)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10,6))
ax0, ax1, ax2, ax3 = axes.flatten()
#Pre-development Hydrograph, 5 in
x_pre_flood = pre_rat_flood_hydrograph[:, 0]
y_pre_flood = pre_rat_flood_hydrograph[:, 1]
ax0.plot(x_pre_flood, y_pre_flood, 'k')
ax0.plot(x_pre_flood, y_pre_flood, 'bo')
ax0.set_title(r'Pre-development (5 in)')
ax0.set_xlabel(r'Time ($hr$)')
ax0.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Pre-development Hydrograph, 5 in
x_post_flood = post_rat_flood_hydrograph[:, 0]
y_post_flood = post_rat_flood_hydrograph[:, 1]
ax1.plot(x_post_flood, y_post_flood, 'k')
ax1.plot(x_post_flood, y_post_flood, 'bo')
ax1.set_title(r'Post-development (5 in)')
ax1.set_xlabel(r'Time ($hr$)')
ax1.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Pre-development Hydrograph, 12 in
x_pre_flood = pre_rat_flood_hydrograph2[:, 0]
y_pre_flood = pre_rat_flood_hydrograph2[:, 1]
ax2.plot(x_pre_flood, y_pre_flood, 'k')
ax2.plot(x_pre_flood, y_pre_flood, 'bo')
ax2.set_title(r'Pre-development (12 in)')
ax2.set_xlabel(r'Time ($hr$)')
ax2.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Pre-development Hydrograph, 12 in
x_post_flood = post_rat_flood_hydrograph2[:, 0]
y_post_flood = post_rat_flood_hydrograph2[:, 1]
ax3.plot(x_post_flood, y_post_flood, 'k')
ax3.plot(x_post_flood, y_post_flood, 'bo')
ax3.set_title(r'Post-development (12 in)')
ax3.set_xlabel(r'Time ($hr$)')
ax3.set_ylabel(r'Discharge ($\frac{ft^{3}}{s}$)')
#Adding a title to all subplots
plt.suptitle("Rational Method Flood Hydrographs")
plt.tight_layout()
plt.show()