Hydro Reservoir

Contents

Overview | Asset Structure | Input File (Standard Format) | Types - Asset Structure | Constructors | Examples | Best Practices | Input File (Advanced Format)

Overview

Hydro Reservoir assets in Macro models hydroelectric storage systems that can store and release water to generate electricity. These assets are defined using either JSON or CSV input files placed in the assets directory, typically named hydrores.json or hydrores.csv.

Asset Structure

A hydro reservoir asset consists of one storage component and three edge components:

  1. Storage Component: Represents the hydroelectric reservoir that stores water
  2. Inflow Edge: Incoming edge representing water inflow to the reservoir
  3. Discharge Edge: Outgoing edge representing electricity production from water release
  4. Spillage Edge: Outgoing edge representing water spillage

Here is a graphical representation of the hydro reservoir asset:

%%{init: {'theme': 'base', 'themeVariables': { 'background': '#D1EBDE' }}}%% flowchart LR subgraph HydroRes direction LR A((Hydro Source)) e1@--> B[Storage] e2@--> C((Electricity)) B e3@--> A e1@{ animate: true } e2@{ animate: true } e3@{ animate: true } end style A r:55px,fill:#FFD700,stroke:black,color:black,stroke-dasharray: 3,5; style B fill:#FFD700,stroke:black,color:black; style C r:48px,fill:#FFD700,stroke:black,color:black,stroke-dasharray: 3,5; linkStyle 0 stroke:#FFD700, stroke-width: 2px; linkStyle 1 stroke:#FFD700, stroke-width: 2px; linkStyle 2 stroke:#FFD700, stroke-width: 2px;

Input File (Standard Format)

The easiest way to include a hydro reservoir asset in a model is to create a new file (either JSON or CSV) and place it in the assets directory together with the other assets.

your_case/
├── assets/
│   ├── hydrores.json    # or hydrores.csv
│   ├── other_assets.json
│   └── ...
├── system/
├── settings/
└── ...

This file can either be created manually, or using the template_asset function, as shown in the Adding an Asset to a System section of the User Guide. The file will be automatically loaded when you run your Macro model.

The following is an example of a hydro reservoir asset input file:

{
    "hydrores": [
        {
            "type": "HydroRes",
            "instance_data": [
                {
                    "id": "MIDAT_conventional_hydroelectric_1",
                    "location": "MIDAT",
                    "hydro_source": "hydro_source",
                    "discharge_can_expand": false,
                    "discharge_can_retire": false,
                    "inflow_can_expand": false,
                    "inflow_can_retire": false,
                    "storage_can_expand": false,
                    "storage_can_retire": false,
                    "storage_constraints": {
                        "MinStorageOutflowConstraint": true
                    },
                    "storage_min_outflow_fraction": 0.109311313,
                    "storage_charge_discharge_ratio": 1.0,
                    "discharge_capacity_size": 29.853,
                    "discharge_existing_capacity": 2806.182,
                    "discharge_fixed_om_cost": 45648,
                    "discharge_efficiency": 1.0,
                    "inflow_availability": {
                        "timeseries": {
                            "path": "system/availability.csv",
                            "header": "MIDAT_conventional_hydroelectric_1"
                        }
                    }
                }
            ]
        }
    ]
}
Global Data vs Instance Data

When working with JSON input files, the global_data field can be used to group data that is common to all instances of the same asset type. This is useful for setting constraints that are common to all instances of the same asset type and avoid repeating the same data for each instance. See the Examples section below for an example.

The following tables outline the attributes that can be set for a hydro reservoir asset.

Essential Attributes

FieldTypeDescription
TypeStringAsset type identifier: "HydroRes"
idStringUnique identifier for the hydro reservoir instance
locationStringGeographic location/node identifier
hydro_sourceStringID of the electricity node in the system that represents the hydro source

Constraints Configuration

Hydro reservoir assets can have different constraints applied to them, and the user can configure them using the following fields:

FieldTypeDescription
storage_constraintsDict{String,Bool}List of constraints applied to the storage component.
discharge_constraintsDict{String,Bool}List of constraints applied to the discharge edge.
inflow_constraintsDict{String,Bool}List of constraints applied to the inflow edge.
spill_constraintsDict{String,Bool}List of constraints applied to the spillage edge.

For example, if the user wants to apply the LongDurationStorageImplicitMinMaxConstraint to the storage component and the RampingLimitConstraint to the discharge edge, the constraints fields should be set as follows:

{
    "storage_constraints": {
        "LongDurationStorageImplicitMinMaxConstraint": true
    },
    "discharge_constraints": {
        "RampingLimitConstraint": true
    }
}

Users can refer to the Adding Asset Constraints to a System section of the User Guide for a list of all the constraints that can be applied to the different components of a hydro reservoir asset.

Default constraints

To simplify the input file and the asset configuration, the following constraints are applied to the hydro reservoir asset by default:

If the storage is a long-duration storage, the following additional constraints are applied:

Investment Parameters

FieldTypeDescriptionUnitsDefault
storage_can_retireBooleanWhether storage capacity can be retired-false
storage_can_expandBooleanWhether storage capacity can be expanded-false
storage_existing_capacityFloat64Initial installed storage capacityMWh0.0
discharge_can_retireBooleanWhether discharge edge capacity can be retired-true
discharge_can_expandBooleanWhether discharge edge capacity can be expanded-true
discharge_existing_capacityFloat64Initial installed discharge edge capacityMW0.0
discharge_capacity_sizeFloat64Unit size for capacity decisions-1.0
inflow_can_retireBooleanWhether inflow edge capacity can be retired-true
inflow_can_expandBooleanWhether inflow edge capacity can be expanded-true
inflow_existing_capacityFloat64Initial installed inflow edge capacityMW0.0
inflow_capacity_sizeFloat64Unit size for capacity decisions-1.0

Additional Investment Parameters

Maximum and minimum capacity constraints

If MaxCapacityConstraint or MinCapacityConstraint are added to the constraints dictionary for the storage or discharge edge, the following parameters are used by Macro:

FieldTypeDescriptionUnitsDefault
storage_max_capacityFloat64Maximum allowed storage capacityMWhInf
storage_min_capacityFloat64Minimum allowed storage capacityMWh0.0
discharge_max_capacityFloat64Maximum allowed discharge edge capacityMWInf
discharge_min_capacityFloat64Minimum allowed discharge edge capacityMW0.0
inflow_max_capacityFloat64Maximum allowed inflow edge capacityMWInf
inflow_min_capacityFloat64Minimum allowed inflow edge capacityMW0.0

Economic Parameters

FieldTypeDescriptionUnitsDefault
storage_investment_costFloat64CAPEX per unit storage capacity$/MWh/yr0.0
storage_fixed_om_costFloat64Fixed O&M costs of the storage component$/MWh/yr0.0
discharge_investment_costFloat64CAPEX per unit discharge edge capacity$/MW/yr0.0
discharge_fixed_om_costFloat64Fixed O&M costs of the discharge edge$/MW/yr0.0
discharge_variable_om_costFloat64Variable O&M costs of the discharge edge$/MWh0.0
inflow_investment_costFloat64CAPEX per unit inflow edge capacity$/MW/yr0.0
inflow_fixed_om_costFloat64Fixed O&M costs of the inflow edge$/MW/yr0.0

Operational Parameters

FieldTypeDescriptionUnitsDefault
inflow_availabilityDictPath to availability file and column name-Empty

Additional Operational Parameters

Minimum Storage Outflow Constraint

If MinStorageOutflowConstraint is added to the constraints dictionary for the storage component, the following parameters are used:

FieldTypeDescriptionUnitsDefault
storage_min_outflow_fractionFloat64Minimum outflow as a fraction of capacityfraction0.0

Storage Charge Discharge Ratio Constraint

If StorageChargeDischargeRatioConstraint is added to the constraints dictionary for the storage component, the following parameters are used:

FieldTypeDescriptionUnitsDefault
storage_charge_discharge_ratioFloat64Ratio between charging and discharging flowsfraction1.0

Ramping limit constraint

If RampingLimitConstraint is added to the constraints dictionary for the discharge edge, the following parameters are used:

FieldTypeDescriptionUnitsDefault
discharge_ramp_up_fractionFloat64Maximum increase in flow between timestepsfraction1.0
discharge_ramp_down_fractionFloat64Maximum decrease in flow between timestepsfraction1.0

Types - Asset Structure

The HydroRes asset is defined as follows:

struct HydroRes <: AbstractAsset
    id::AssetId
    hydrostor::AbstractStorage{<:Electricity}
    discharge_edge::Edge{<:Electricity}
    inflow_edge::Edge{<:Electricity}
    spill_edge::Edge{<:Electricity}
end

Constructors

Default constructor

HydroRes(id::AssetId, hydrostor::AbstractStorage{<:Electricity}, discharge_edge::Edge{<:Electricity}, inflow_edge::Edge{<:Electricity}, spill_edge::Edge{<:Electricity})

Factory constructor

make(asset_type::Type{HydroRes}, data::AbstractDict{Symbol,Any}, system::System)
FieldTypeDescription
asset_typeType{HydroRes}Macro type of the asset
dataAbstractDict{Symbol,Any}Dictionary containing the input data for the asset
systemSystemSystem to which the asset belongs

Examples

This section contains examples of how to use the hydro reservoir asset in a Macro model.

Simple Hydro Reservoir with Fixed Capacity

This example shows a hydro reservoir asset with existing and fixed capacity (capacity cannot be expanded or retired), minimum outflow fraction of 0.1, and an availability time series for the inflow edge loaded from a CSV file. A MinStorageOutflowConstraint constraint is applied to the storage component to ensure that the outflow is at least 10% of the capacity.

JSON Format:

{
    "hydrores": [
        {
            "type": "HydroRes",
            "instance_data": [
                {
                    "id": "Fixed_Hydro_SE",
                    "location": "SE",
                    "hydro_source": "hydro_source",
                    "discharge_can_expand": false,
                    "discharge_can_retire": false,
                    "inflow_can_expand": false,
                    "inflow_can_retire": false,
                    "storage_can_expand": false,
                    "storage_can_retire": false,
                    "storage_constraints": {
                        "MinStorageOutflowConstraint": true
                    },
                    "storage_min_outflow_fraction": 0.1,
                    "discharge_capacity_size": 1.0,
                    "discharge_existing_capacity": 1000.0,
                    "discharge_fixed_om_cost": 10000.0,
                    "discharge_efficiency": 1.0,
                    "inflow_availability": {
                        "timeseries": {
                            "path": "system/availability.csv",
                            "header": "Fixed_Hydro_SE"
                        }
                    }
                }
            ]
        }
    ]
}

CSV Format:

Typeidlocationhydro_sourcedischarge_can_expanddischarge_can_retireinflow_can_expandinflow_can_retirestorage_can_expandstorage_can_retirestorage_constraints–MinStorageOutflowConstraintstorage_min_outflow_fractiondischarge_capacity_sizedischarge_existing_capacitydischarge_fixed_om_costdischarge_efficiencyinflow_availability–timeseries–pathinflow_availability–timeseries–header
HydroResFixed_Hydro_SESEhydro_sourcefalsefalsefalsefalsefalsefalsetrue0.11.01000.010000.01.0system/availability.csvFixed_Hydro_SE

Multiple Hydro Reservoir Assets in Different Zones

This example shows three hydro reservoir assets with existing and fixed capacity (capacity cannot be expanded or retired) located in the MIDAT, NE, and SE regions. A RampingLimitConstraint constraint is applied to the discharge edge with a ramping limit of 0.83. A MinStorageOutflowConstraint constraint is applied to the storage component to ensure that the outflow is at least 10% of the capacity. Finally, the storage component is set to be a long-duration storage with a LongDurationStorageImplicitMinMaxConstraint constraint applied to it.

JSON Format:

Note that the global_data field is used to set the fields and constraints that are common to all instances of the same asset type.

{
    "hydrores": [
        {
            "type": "HydroRes",
            "global_data": {
                "hydro_source": "hydro_source",
                "discharge_constraints": {
                    "RampingLimitConstraint": true
                },
                "discharge_can_expand": false,
                "discharge_can_retire": false,
                "inflow_can_expand": false,
                "inflow_can_retire": false,
                "storage_can_expand": false,
                "storage_can_retire": false,
                "storage_long_duration": true,
                "storage_constraints": {
                    "MinStorageOutflowConstraint": true,
                    "LongDurationStorageImplicitMinMaxConstraint": true
                }
            },
            "instance_data": [
                {
                    "id": "MIDAT_conventional_hydroelectric_1",
                    "location": "MIDAT",
                    "storage_min_outflow_fraction": 0.109311313,
                    "discharge_capacity_size": 29.853,
                    "discharge_existing_capacity": 2806.182,
                    "discharge_fixed_om_cost": 45648,
                    "discharge_ramp_down_fraction": 0.83,
                    "discharge_ramp_up_fraction": 0.83,
                    "discharge_efficiency": 1.0,
                    "inflow_availability": {
                        "timeseries": {
                            "path": "system/availability.csv",
                            "header": "MIDAT_conventional_hydroelectric_1"
                        }
                    }
                },
                {
                    "id": "NE_conventional_hydroelectric_1",
                    "location": "NE",
                    "storage_min_outflow_fraction": 0.095,
                    "discharge_capacity_size": 24.13,
                    "discharge_existing_capacity": 4729.48,
                    "discharge_fixed_om_cost": 45648,
                    "discharge_ramp_down_fraction": 0.083,
                    "discharge_ramp_up_fraction": 0.083,
                    "discharge_efficiency": 1.0,
                    "inflow_availability": {
                        "timeseries": {
                            "path": "system/availability.csv",
                            "header": "NE_conventional_hydroelectric_1"
                        }
                    }
                },
                {
                    "id": "SE_conventional_hydroelectric_1",
                    "location": "SE",
                    "storage_min_outflow_fraction": 0.135129141,
                    "discharge_capacity_size": 31.333,
                    "discharge_existing_capacity": 11123.215,
                    "discharge_fixed_om_cost": 45648,
                    "discharge_ramp_down_fraction": 0.083,
                    "discharge_ramp_up_fraction": 0.083,
                    "discharge_efficiency": 1.0,
                    "inflow_availability": {
                        "timeseries": {
                            "path": "system/availability.csv",
                            "header": "SE_conventional_hydroelectric_1"
                        }
                    }
                }
            ]
        }
    ]
}

CSV Format:

Typeidlocationhydro_sourcedischarge_can_expanddischarge_can_retireinflow_can_expandinflow_can_retirestorage_can_expandstorage_can_retirestorage_constraints–MinStorageOutflowConstraintstorage_min_outflow_fractiondischarge_capacity_sizedischarge_existing_capacitydischarge_fixed_om_costdischarge_ramp_down_fractiondischarge_ramp_up_fractiondischarge_efficiencyinflow_availability–timeseries–pathinflow_availability–timeseries–header
HydroResMIDAT_conventional_hydroelectric_1MIDAThydro_sourcefalsefalsefalsefalsefalsefalsetrue0.10931131329.8532806.182456480.830.831.0system/availability.csvMIDAT_conventional_hydroelectric_1
HydroResNE_conventional_hydroelectric_1NEhydro_sourcefalsefalsefalsefalsefalsefalsetrue0.09524.134729.48456480.0830.0831.0system/availability.csvNE_conventional_hydroelectric_1
HydroResSE_conventional_hydroelectric_1SEhydro_sourcefalsefalsefalsefalsefalsefalsetrue0.13512914131.33311123.215456480.0830.0831.0system/availability.csvSE_conventional_hydroelectric_1

Best Practices

  1. Use global data for common constraints: Use the global_data field to set the fields and constraints that are common to all instances of the same asset type.
  2. Set realistic minimum outflow fractions: These should reflect environmental and operational requirements
  3. Use meaningful IDs: Choose descriptive identifiers that indicate location and technology type
  4. Consider availability profiles: Use availability time series to model seasonal variations in water inflow
  5. Set appropriate ramping limits: These should reflect the actual operational characteristics of the hydro plant
  6. Validate costs: Ensure investment and O&M costs are in appropriate units and time periods
  7. Test configurations: Start with simple configurations and gradually add complexity

Input File (Advanced Format)

Macro provides an advanced format for defining hydro reservoir assets, offering users and modelers detailed control over asset specifications. This format builds upon the standard format and is ideal for those who need more comprehensive customization.

To understand the advanced format, consider the graph representation and the type definition of a hydro reservoir asset. The input file mirrors this hierarchical structure.

A hydro reservoir asset in Macro is composed of a storage component, represented by a Storage object, and three edges, each represented by an Edge object. The input file for a hydro reservoir asset is therefore organized as follows:

{
    "storage":{
        // ... storage-specific attributes ...
    },
    "edges":{
        "inflow_edge": {
            // ... inflow_edge-specific attributes ...
        },
        "discharge_edge": {
            // ... discharge_edge-specific attributes ...
        },
        "spill_edge": {
            // ... spill_edge-specific attributes ...
        }
    }
}

Each top-level key (e.g., "storage" or "edges") denotes a component type. The second-level keys either specify the attributes of the component (when there is a single instance) or identify the instances of the component (e.g., "discharge_edge", "inflow_edge", "spill_edge") when there are multiple instances. For multiple instances, a third-level key details the attributes for each instance.

Below is an example of an input file for a hydro reservoir asset that sets up a single asset in the SE region with detailed edge specifications.

{
    "hydrores": [
        {
            "type": "HydroRes",
            "global_data": {
                "storage": {
                    "commodity": "Electricity",
                    "can_expand": false,
                    "can_retire": false,
                    "constraints": {
                        "MinStorageOutflowConstraint": true
                    }
                },
                "edges": {
                    "inflow_edge": {
                        "type": "Electricity",
                        "unidirectional": true,
                        "start_vertex": "hydro_source",
                        "has_capacity": true,
                        "constraints": {
                            "MustRunConstraint": true
                        }
                    },
                    "discharge_edge": {
                        "type": "Electricity",
                        "unidirectional": true,
                        "has_capacity": true,
                        "can_expand": false,
                        "can_retire": false,
                        "constraints": {
                            "CapacityConstraint": true,
                            "RampingLimitConstraint": true
                        }
                    },
                    "spill_edge": {
                        "type": "Electricity",
                        "unidirectional": true,
                        "end_vertex": "hydro_source",
                        "can_expand": false,
                        "can_retire": false,
                        "has_capacity": false
                    }
                }
            },
            "instance_data": [
                {
                    "id": "SE_conventional_hydroelectric_1",
                    "storage": {
                        "min_outflow_fraction": 0.135129141,
                        "charge_discharge_ratio": 1.0
                    },
                    "edges": {
                        "inflow_edge": {
                            "efficiency": 1.0,
                            "availability": {
                                "timeseries": {
                                    "path": "assets/availability.csv",
                                    "header": "SE_conventional_hydroelectric_1"
                                }
                            }
                        },
                        "discharge_edge": {
                            "end_vertex": "elec_SE",
                            "capacity_size": 31.333,
                            "existing_capacity": 11123.215,
                            "fixed_om_cost": 45648,
                            "ramp_down_fraction": 0.083,
                            "ramp_up_fraction": 0.083,
                            "efficiency": 1.0
                        }
                    }
                }
            ]
        }
    ]
}

Key Points

  • The global_data field is utilized to define attributes and constraints that apply universally to all instances of a particular asset type.
  • The start_vertex and end_vertex fields indicate the nodes to which the edges are connected. These nodes must be defined in the nodes.json file.
  • By default, both the discharge and inflow edges are allowed to have capacity variables and constraints, as this represents the main capacity decision for the hydro facility (see note below).
  • The inflow edge uses availability time series to model seasonal variations in water inflow.
  • For a comprehensive list of attributes that can be configured for the storage and edge components, refer to the storage and edges pages of the Macro manual.
Prefixes

Users can apply prefixes to adjust parameters for the components of a hydro reservoir asset, even when using the standard format. For instance, discharge_can_retire will adjust the can_retire parameter for the discharge edge, and discharge_existing_capacity will adjust the existing_capacity parameter for the discharge edge. Below are the prefixes available for modifying parameters for the components of a hydro reservoir asset:

  • storage_ for the storage component
  • discharge_ for the discharge edge
  • inflow_ for the inflow edge
  • spill_ for the spill edge