Understanding Randomness and Hydropower

In this blog, we will explore how randomness and numpy can be used in a practical example related to water resource engineering and hydropower. We’ll create a program that simulates the operation of a reservoir and calculates hydropower generation.

Importing Necessary Libraries

import random
import numpy as np
  • random: This module helps us generate random numbers.
  • numpy (imported as np): This library is used for numerical operations, especially with arrays and matrices.

Defining the Reservoir Class

A class in Python is a way to create complex data structures that can hold both data and functions. Here, we define a Reservoir class to model our reservoir.

class Reservoir:
    def __init__(self, name, capacity, initial_storage, a, b, c):
        self.name = name
        self.capacity = capacity
        self.storage = initial_storage
        self.a = a 
        self.b = b
        self.c = c
  • __init__: This is a special function called a constructor. It initializes the reservoir’s attributes when we create an instance of the class.
    • name: The name of the reservoir.
    • capacity: The maximum storage capacity of the reservoir.
    • initial_storage: The initial amount of water stored in the reservoir.
    • a, b, c: Coefficients used to calculate the height of the water based on storage.

Updating Storage

    def storageUpdate(self, inflow, outflow, loss):
        self.storage += inflow - outflow - loss
        if self.storage > self.capacity:
            self.storage = self.capacity
        elif self.storage < 0:
            self.storage = 0
        return self.storage
  • storageUpdate: This function updates the reservoir’s storage based on inflow, outflow, and losses.
    • inflow: Water flowing into the reservoir.
    • outflow: Water flowing out of the reservoir.
    • loss: Water lost due to evaporation or seepage.

Calculating Water Height

    def calculate_height(self):
        height = self.a + self.b * self.storage + self.c * self.storage**2
        return height
  • calculate_height: This function calculates the height of the water based on the current storage using a quadratic formula.

Calculating Hydropower

    def calculate_power(self, outflow):
        height = self.calculate_height()
        eff = 0.9  # Efficiency of the hydropower plant
        rho = 1000  # Density of water (kg/m^3)
        g = 9.81  # Acceleration due to gravity (m/s^2)
        power = eff * rho * g * height * outflow  # Power in watts
        return power / 1e6  # Convert to Megawatts (MW)
  • calculate_power: This function calculates the power generated by the hydropower plant.
    • eff: Efficiency of the hydropower plant (usually less than 1).
    • rho: Density of water.
    • g: Acceleration due to gravity.
    • height: Height of the water column.
    • outflow: Water flowing out of the reservoir.

Simulation Parameters

reservoir_name = "Koshi"
reservoir_capacity = 1000e6
initial_storage = 1000e6
a, b, c = 10, 1e-9, 1e-18  # Coefficients for height calculation
num_days = 30
max_inflow = 25e6
daily_outflow = 15e6
loss = 1e6
  • reservoir_name: Name of the reservoir.
  • reservoir_capacity: Maximum capacity of the reservoir in cubic meters.
  • initial_storage: Initial storage in cubic meters.
  • a, b, c: Coefficients for the height calculation.
  • num_days: Number of days to simulate.
  • max_inflow: Maximum possible daily inflow in cubic meters.
  • daily_outflow: Daily outflow in cubic meters.
  • loss: Daily water loss in cubic meters.

Creating the Reservoir

reservoir = Reservoir(reservoir_name, reservoir_capacity, initial_storage, a, b, c)
  • We create an instance of the Reservoir class with the specified parameters.

Generating Random Daily Inflows

daily_inflows = np.random.randint(5, max_inflow, size=num_days)
  • np.random.randint: Generates random integers between 5 and max_inflow for num_days.

Simulating Storage and Hydropower Generation

daily_storage = []
daily_height = []
daily_power = []

for day in range(num_days):
    inflow = daily_inflows[day]
    storage = reservoir.storageUpdate(inflow, daily_outflow, loss)
    height = reservoir.calculate_height()
    power = reservoir.calculate_power(daily_outflow)
    daily_storage.append(storage)
    daily_height.append(height)
    daily_power.append(power)
  • For each day, we:
    • Update the storage.
    • Calculate the height.
    • Calculate the power generated.
    • Store these values in lists.

Printing Results

print("Day \t Inflow \t Storage(MCM) \t Height(m) \t Power(GW-day)")
for day in range(num_days):
    print(f"{day + 1} \t\t {daily_inflows[day] / 1e6:.2f} \t\t {daily_storage[day] / 1e6:.2f}\t\t{daily_height[day]:.2f}\t\t{daily_power[day] / 1000:.2f}")
  • We print the results for each day:
    • day + 1: Day number.
    • daily_inflows[day] / 1e6: Inflow in million cubic meters (MCM).
    • daily_storage[day] / 1e6: Storage in MCM.
    • daily_height[day]: Height in meters.
    • daily_power[day] / 1000: Power in gigawatts-day (GW-day).

Summary

In this example, we simulated the operation of a reservoir over 30 days, accounting for random inflows, outflows, and losses. We calculated the height of the water and the power generated by a hydropower plant. This demonstrates how randomness and numpy can be used in practical examples related to water resource engineering and hydropower.

Script

import random
import numpy as np

# Reservoir class is defined here
class Reservoir:
    def __init__(self, name, capacity, initial_storage, a, b, c):
        self.name = name
        self.capacity = capacity
        self.storage = initial_storage
        self.a = a
        self.b = b
        self.c = c
    
    def storageUpdate(self, inflow, outflow, loss):
        self.storage += inflow - outflow - loss
        if self.storage > self.capacity:
            self.storage = self.capacity
        elif self.storage < 0:
            self.storage = 0
        return self.storage
    
    def calculate_height(self):
        height = self.a + self.b * self.storage + self.c * self.storage ** 2
        return height
    
    def calculate_power(self, outflow):
        height = self.calculate_height()
        eff = 0.9  # efficiency
        rho = 1000  # density of water (kg/m^3)
        g = 9.81  # acceleration due to gravity (m/s^2)
        power = eff * rho * g * height * outflow  # Power in watts
        return power / 1e6  # convert to Megawatts (MW)
    
# Simulation parameters
reservoir_name = "Koshi"
reservoir_capacity = 1000e6  # 1000 million cubic meters
initial_storage = 1000e6  # 1000 million cubic meters
a, b, c = 10, 1e-9, 1e-18  # coefficients for height calculation
num_days = 30  # number of days to simulate
max_inflow = 25e6  # maximum inflow per day in cubic meters
daily_outflow = 15e6  # daily outflow in cubic meters
loss = 1e6  # daily loss in cubic meters

# Create reservoir
reservoir = Reservoir(reservoir_name, reservoir_capacity, initial_storage, a, b, c)

# Generate random daily inflows for a month (30 days)
np.random.seed(42)
daily_inflows = np.random.randint(5, max_inflow, size=num_days)

# Simulate storage and hydropower generation over the month
daily_storage = []
daily_height = []
daily_power = []

for day in range(num_days):
    inflow = daily_inflows[day]
    storage = reservoir.storageUpdate(inflow, daily_outflow, loss)
    height = reservoir.calculate_height()
    power = reservoir.calculate_power(daily_outflow)
    daily_storage.append(storage)
    daily_height.append(height)
    daily_power.append(power)

# Print results
print("Day \t Inflow \t Storage(MCM) \t Height(m) \t Power(GW-day)")
for day in range(num_days):
    print(f"{day + 1} \t\t {daily_inflows[day] / 1e6:.2f} \t\t {daily_storage[day] / 1e6:.2f}\t\t{daily_height[day]:.2f}\t\t{daily_power[day] / 1000:.2f}")

Yogesh SN