Virtual Reservoir - Building

The data for this case is available in the folder data/case_5

Virtual Reservoir overview

Before getting into the details of the case, let's understand the concept of a virtual reservoir.

A virtual reservoir is a mechanism to aggregate multiple hydro units into a single entity. More than one Asset Owner can be linked into the same Virtual Reservoir

Each Asset Owner has an inflow allocation, which is the percentage of inflow that each Asset Owner has in the Virtual Reservoir. This percentage is also used to compute the initial energy in the Virtual Reservoir for each Asset Owner.

Case overview

In this case, we will have two Hydro Units and two Asset Owners linked to a single Virtual Reservoir. The inflow allocation for the first Asset Owner is 40%, and for the second Asset Owner is 60%.

The second Asset Owner will place higher bids than the first Asset Owner. So what we expect is that the first Asset Owner will be generating more energy in the beginning and, as the energy of the first Asset Owner decreases, the second Asset Owner will start generating more energy.

Also, the hydro units will be in a cascade relationship, where the first hydro unit will be able to turbine and spill water to the second hydro unit.

Creating the case

We'll start by importing the necessary packages.

using Dates
using DataFrames
using IARA

The case will have the following characteristics

number_of_periods = 3
number_of_scenarios = 1
number_of_subperiods = 4
maximum_number_of_bidding_segments = 1
subperiod_duration_in_hours = 1000.0 / number_of_subperiods
cycle_duration_in_hours =
    subperiod_duration_in_hours * number_of_subperiods * number_of_periods

Let's define a few conversion factors that we will use later.

MW_to_GWh = subperiod_duration_in_hours * 1e-3
m3_per_second_to_hm3_per_hour = 3600.0 / 1e6

As we have done in the previous tutorials, we will start by creating a new case.

const PATH_CASE = joinpath(@__DIR__, "data", "case_5")

db = IARA.create_study!(PATH_CASE;
    number_of_periods = number_of_periods,
    number_of_scenarios = number_of_scenarios,
    number_of_subperiods = number_of_subperiods,
    initial_date_time = "2020",
    subperiod_duration_in_hours = [
        subperiod_duration_in_hours for _ in 1:number_of_subperiods
    ],
    policy_graph_type = IARA.Configurations_PolicyGraphType.LINEAR,
    cycle_discount_rate = 0.0,
    cycle_duration_in_hours = cycle_duration_in_hours,
    demand_deficit_cost = 500.0,
    hydro_minimum_outflow_violation_cost = 600.0,
    number_of_virtual_reservoir_bidding_segments = maximum_number_of_bidding_segments,
    clearing_hydro_representation = IARA.Configurations_ClearingHydroRepresentation.VIRTUAL_RESERVOIRS,
    clearing_bid_source = IARA.Configurations_ClearingBidSource.HEURISTIC_BIDS,
)

Zone and Bus

Let's add a zone and a bus to our case. This case will have a single zone and a single bus for simplicity.

IARA.add_zone!(db; label = "zone_1")

IARA.add_bus!(db; label = "bus_1", zone_id = "zone_1")

Hydro Unit

Now we can add our hydro units that will be linked to the virtual reservoir.

IARA.add_hydro_unit!(db;
    label = "hydro_1",
    initial_volume = 100.0,
    bus_id = "bus_1",
    parameters = DataFrame(;
        date_time = [DateTime(0)],
        existing = 1,
        production_factor = 1000.0 * m3_per_second_to_hm3_per_hour,
        max_generation = 400.0,
        min_volume = 0.0,
        max_turbining = 400.0 / m3_per_second_to_hm3_per_hour, # maybe it is 0.4 instead of 400
        max_volume = 2000.0,
        min_outflow = 0.3 / m3_per_second_to_hm3_per_hour,
        om_cost = 10.0,
    ),
)

IARA.add_hydro_unit!(db;
    label = "hydro_2",
    initial_volume = 0.0,
    bus_id = "bus_1",
    parameters = DataFrame(;
        date_time = [DateTime(0)],
        existing = 1,
        production_factor = 1000.0 * m3_per_second_to_hm3_per_hour,
        max_generation = 400.0,
        max_turbining = 400.0 / m3_per_second_to_hm3_per_hour,
        min_volume = 0.0,
        max_volume = 0.0,
        min_outflow = 0.0,
        om_cost = 100.0,
    ),
)

Setting Hydro Unit relations

IARA.set_hydro_turbine_to!(db, "hydro_1", "hydro_2")
IARA.set_hydro_spill_to!(db, "hydro_1", "hydro_2")

Asset Owner

Let's add two asset owners to our case. Both of them will be price makers.

IARA.add_asset_owner!(db;
    label = "asset_owner_1",
    price_type = IARA.AssetOwner_PriceType.PRICE_MAKER,
    segment_fraction = [1.0],
    risk_factor = [0.1],
)

IARA.add_asset_owner!(db;
    label = "asset_owner_2",
    price_type = IARA.AssetOwner_PriceType.PRICE_MAKER,
    segment_fraction = [1.0],
    risk_factor = [0.9],
)

Virtual Reservoir

Now we can add the virtual reservoir to our case. Notice that we are setting the inflow allocation and linking the asset owners and hydro units.

IARA.add_virtual_reservoir!(db;
    label = "reservoir_1",
    assetowner_id = ["asset_owner_1", "asset_owner_2"],
    inflow_allocation = [0.4, 0.6],
    hydrounit_id = ["hydro_1", "hydro_2"],
)

Demand

This case will have a single demand, which we can add with the function IARA.add_demand_unit!.

IARA.add_demand_unit!(db;
    label = "dem_1",
    parameters = DataFrame(;
        date_time = [DateTime(0)],
        existing = [1],
    ),
    bus_id = "bus_1",
)

Time Series

For this case, we have added time series files for the

  • Demand
  • Inflow

They are available in the folder data/case_5

Let's take a look into each of these files before linking them.

IARA.time_series_dataframe(
    joinpath(PATH_CASE, "demand.csv"),
)
12×4 DataFrame
Rowperiodscenariosubperioddem_1
Int64Int64Int64Float32
11115.0
21127.0
31139.0
411411.0
521113.0
621215.0
721317.0
821419.0
931121.0
1031223.0
1131325.0
1231427.0
IARA.link_time_series_to_file(
    db,
    "DemandUnit";
    demand = "demand",
)

To simplify our case, we are setting the inflow to zero, so we are only working with the initial volume of the first Hydro Unit.

IARA.time_series_dataframe(
    joinpath(PATH_CASE, "inflow.csv"),
)
12×5 DataFrame
Rowperiodscenariosubperiodhydro_1_gauging_stationhydro_2_gauging_station
Int64Int64Int64Float32Float32
11110.00.0
21120.00.0
31130.00.0
41140.00.0
52110.00.0
62120.00.0
72130.00.0
82140.00.0
93110.00.0
103120.00.0
113130.00.0
123140.00.0
IARA.link_time_series_to_file(
    db,
    "HydroUnit";
    inflow = "inflow",
)

Closing the study

IARA.close_study!(db)

This page was generated using Literate.jl.