Battery

Contents

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

Overview

Battery assets in Macro represent electricity storage technologies that can charge from and discharge to the electricity network. These assets are defined using either JSON or CSV input files placed in the assets directory, typically named electricity_stor.json or electricity_stor.csv.

Asset Structure

A battery storage asset consists of three main components:

  1. Storage Component: Tracks the energy level in the battery over time
  2. Charge Edge: Represents electricity flow from the grid to the battery
  3. Discharge Edge: Represents electricity flow from the battery to the grid

Here is a graphical representation of the battery asset:

%%{init: {'theme': 'base', 'themeVariables': { 'background': '#D1EBDE' }}}%% flowchart LR subgraph Battery direction BT A((Electricity)) e1@-->|Charge| B[Storage] B e2@-->|Discharge| A e1@{ animate: true } e2@{ animate: true } end style A font-size:19px,r:55px,fill:#FFD700,stroke:black,color:black,stroke-dasharray: 3,5; style B fill:#FFD700,stroke:black,color:black; linkStyle 0,1 stroke:#FFD700, stroke-width: 2px;

Symmetric and Asymmetric Battery

Macro supports a variety of battery technologies, both with symmetric and asymmetric charge/discharge capacities. Examples of symmetric batteries are lithium-ion batteries, while asymmetric batteries are thermal storage systems.

The user can configure the battery asset to be symmetric or asymmetric simply by using the input file as described in the following section. By default, the battery asset is configured to be symmetric.

Input File (Standard Format)

The easiest way to include a battery 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/
│   ├── electricity_stor.json    # or electricity_stor.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 battery asset input file:

{
    "elec_stor": [
        {
            "type": "Battery",
            "global_data": {
                "storage_constraints": {
                    "StorageMinDurationConstraint": true,
                    "StorageMaxDurationConstraint": true,
                }
            },
            "instance_data": [
                {
                    "id": "battery_1_SE",
                    "location": "SE",
                    "storage_investment_cost": 10000,
                    "storage_fixed_om_cost": 500,
                    "storage_max_duration": 10,
                    "storage_min_duration": 1,
                    "discharge_investment_cost": 20000,
                    "discharge_fixed_om_cost": 1000,
                    "discharge_variable_om_cost": 1,
                    "charge_variable_om_cost": 1,
                    "discharge_efficiency": 0.95,
                    "charge_efficiency": 0.95
                }
            ]
        }
    ]
}
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 outlines the attributes that can be set for a battery asset.

Essential Attributes

FieldTypeDescription
TypeStringAsset type identifier: "Battery"
idStringUnique identifier for the battery instance
locationStringGeographic location/node identifier

Constraints configuration

Battery 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.
charge_constraintsDict{String,Bool}List of constraints applied to the charge edge.

For example, if the user wants to apply the StorageMinDurationConstraint to the storage component and the MinFlowConstraint to the discharge edge, the storage_constraints and discharge_constraints fields should be set to {"StorageMinDurationConstraint": true} and {"MinFlowConstraint": true}, respectively:

{
    "storage_constraints": {
        "StorageMinDurationConstraint": true
    },
    "discharge_constraints": {
        "MinFlowConstraint": 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 a battery asset.

Default constraints

To simplify the input file and the asset configuration, the following constraints are applied to the battery 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-true
storage_can_expandBooleanWhether storage capacity can be expanded-true
storage_existing_capacityFloat64Initial installed storage capacityMWh0.0
storage_capacity_sizeFloat64Unit size for capacity decisions-1.0
discharge_can_retireBooleanWhether discharge capacity can be retired-true
discharge_can_expandBooleanWhether discharge capacity can be expanded-true
discharge_existing_capacityFloat64Initial installed discharge capacityMWh/hr0.0
discharge_capacity_sizeFloat64Unit size for capacity decisions-1.0
Asymmetric battery

If the battery is asymmetric, the following investment parameters are also used:

FieldTypeDescriptionUnitsDefault
charge_has_capacityBooleanWhether the charge edge has capacity variables and limits-false
charge_can_retireBooleanWhether charge capacity can be retired-false
charge_can_expandBooleanWhether charge capacity can be expanded-false
charge_existing_capacityFloat64Initial installed charge capacityMWh/hr0.0
charge_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 any of the three components, 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 capacityMWh/hrInf
discharge_min_capacityFloat64Minimum allowed discharge capacityMWh/hr0.0
charge_max_capacityFloat64Maximum allowed charge capacityMWh/hrInf
charge_min_capacityFloat64Minimum allowed charge capacityMWh/hr0.0

Economic Parameters

FieldTypeDescriptionUnitsDefault
storage_investment_costFloat64CAPEX per unit storage capacity$/MWh0.0
storage_annualized_investment_costUnion{Nothing,Float64}Annualized CAPEX$/MWh/yrcalculated
storage_fixed_om_costFloat64Fixed O&M costs of the storage component$/MWh/yr0.0
storage_variable_om_costFloat64Variable O&M costs of the storage component$/MWh0.0
storage_waccFloat64Weighted average cost of capitalfraction0.0
storage_lifetimeIntAsset lifetime in yearsyears1
storage_capital_recovery_periodIntInvestment recovery periodyears1
storage_retirement_periodIntRetirement periodyears0
discharge_investment_costFloat64CAPEX per unit discharge capacity$/MW0.0
discharge_annualized_investment_costUnion{Nothing,Float64}Annualized CAPEX$/MW/yrcalculated
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
discharge_waccFloat64Weighted average cost of capitalfraction0.0
discharge_lifetimeIntAsset lifetime in yearsyears1
discharge_capital_recovery_periodIntInvestment recovery periodyears1
discharge_retirement_periodIntRetirement periodyears0
charge_variable_om_costFloat64Variable O&M costs of the charge edge$/MWh0.0
Asymmetric battery

If the battery is asymmetric, the following economic parameters are also used:

FieldTypeDescriptionUnitsDefault
charge_investment_costFloat64CAPEX per unit charge capacity$/MW0.0
charge_annualized_investment_costUnion{Nothing,Float64}Annualized CAPEX$/MW/yrcalculated
charge_fixed_om_costFloat64Fixed O&M costs of the charge edge$/MW/yr0.0

Charge and Discharge Efficiency

FieldTypeDescriptionDefault
discharge_efficiencyFloat64Efficiency of discharging process1.0
charge_efficiencyFloat64Efficiency of charging process1.0

Operational Parameters

FieldTypeDescriptionUnitsDefault
storage_loss_fractionFloat64Fraction of stored energy lost per timestepfraction0.0

Additional Operational Parameters

Storage duration constraints

If StorageMaxDurationConstraint or StorageMinDurationConstraint are added to the constraints dictionary for the storage component, the following parameters are used:

FieldTypeDescriptionUnitsDefault
storage_max_durationFloat64Maximum storage durationhours0.0
storage_min_durationFloat64Minimum storage durationhours0.0

Maximum and minimum storage level constraints

If MaxStorageLevelConstraint or MinStorageLevelConstraint are added to the constraints dictionary for the storage component, the following parameters are used:

FieldTypeDescriptionUnitsDefault
storage_max_storage_levelFloat64Maximum storage level as fraction of capacityfraction0.0
storage_min_storage_levelFloat64Minimum storage level as fraction of capacityfraction0.0

Storage charge/discharge ratio constraint

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

FieldTypeDescriptionUnitsDefault
storage_charge_discharge_ratioFloat64Ratio between charging and discharging ratesfraction1.0

Long-duration storage constraint

If LongDurationStorageImplicitMinMaxConstraint is added to the constraints dictionary for the storage component, the following parameter is used:

FieldTypeDescriptionDefault
storage_long_durationBooleanWhether this is long-duration storagefalse

Minimum flow constraint

If MinFlowConstraint is added to the constraints dictionary for the discharge edge, the following parameter is used:

FieldTypeDescriptionUnitsDefault
discharge_min_flow_fractionFloat64Minimum discharge as fraction of capacityfraction0.0
charge_min_flow_fractionFloat64Minimum charge as fraction of capacityfraction0.0

Ramping limit constraint

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

FieldTypeDescriptionUnitsDefault
discharge_ramp_up_fractionFloat64Maximum increase in discharge between timestepsfraction1.0
discharge_ramp_down_fractionFloat64Maximum decrease in discharge between timestepsfraction1.0
charge_ramp_up_fractionFloat64Maximum increase in charge between timestepsfraction1.0
charge_ramp_down_fractionFloat64Maximum decrease in charge between timestepsfraction1.0

Types - Asset Structure

The Battery asset is defined as follows:

struct Battery <: AbstractAsset
    id::AssetId
    battery_storage::AbstractStorage{<:Electricity}
    discharge_edge::Edge{<:Electricity}
    charge_edge::Edge{<:Electricity}
end

Constructors

Default constructor

Battery(id::AssetId, storage::AbstractStorage{<:Electricity}, discharge_edge::Edge{<:Electricity}, charge_edge::Edge{<:Electricity})

Factory constructor

make(asset_type::Type{Battery}, data::AbstractDict{Symbol,Any}, system::System)
FieldTypeDescription
asset_typeType{Battery}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 battery asset in a Macro model.

Two batteries in the same zone "SE"

This example shows two batteries in the same zone "SE" with different investment costs and O&M costs. The discharge efficiency and charge efficiency are set to 0.95 and 0.92, respectively. Both batteries have the StorageMinDurationConstraint and StorageMaxDurationConstraint constraints applied to the storage component.

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.

{
    "elec_stor": [
        {
            "type": "Battery",
            "global_data": {
                "storage_constraints": {
                    "StorageMinDurationConstraint": true,
                    "StorageMaxDurationConstraint": true,
                }
            },
            "instance_data": [
                {
                    "id": "battery_1_SE",
                    "location": "SE",
                    "storage_investment_cost": 10000,
                    "storage_fixed_om_cost": 500,
                    "storage_max_duration": 10,
                    "storage_min_duration": 1,
                    "discharge_investment_cost": 20000,
                    "discharge_fixed_om_cost": 1000,
                    "discharge_variable_om_cost": 1,
                    "charge_variable_om_cost": 1,
                    "discharge_efficiency": 0.95,
                    "charge_efficiency": 0.95
                },
                {
                    "id": "battery_2_SE",
                    "location": "SE",
                    "storage_investment_cost": 15000,
                    "storage_fixed_om_cost": 800,
                    "storage_max_duration": 4,
                    "storage_min_duration": 1,
                    "discharge_investment_cost": 25000,
                    "discharge_fixed_om_cost": 1200,
                    "discharge_variable_om_cost": 1.2,
                    "charge_variable_om_cost": 1.2,
                    "discharge_efficiency": 0.92,
                    "charge_efficiency": 0.92
                }
            ]
        }
    ]
}

CSV Format:

Typeidlocationstorage_constraints–StorageMinDurationConstraintstorage_constraints–StorageMaxDurationConstraintstorage_investment_coststorage_fixed_om_coststorage_max_durationstorage_min_durationdischarge_investment_costdischarge_fixed_om_costdischarge_variable_om_costcharge_variable_om_costdischarge_efficiencycharge_efficiency
Batterybattery_1_SESEtruetrue10000500101200001000110.950.95
Batterybattery_2_SESEtruetrue15000800412500012001.21.20.920.92

Pumped Hydro Storage

This example shows a pumped hydro storage asset with a fixed discharge and storage capacity (capacity cannot be expanded or retired) and a minimum discharge flow constraint of 0.5.

JSON Format:

{
    "elec_stor": [
        {
            "type": "Battery",
            "global_data": {
                "discharge_can_expand": false,
                "discharge_can_retire": false,
                "storage_can_expand": false,
                "storage_can_retire": false,
                "discharge_constraints": {
                    "MinFlowConstraint": true
                }
            },
            "instance_data": [
                {
                    "id": "pumpedhydro_SE",
                    "location": "SE",
                    "discharge_capacity_size": 200,
                    "discharge_existing_capacity": 5000,
                    "discharge_fixed_om_cost": 40000,
                    "discharge_min_flow_fraction": 0.5,
                    "discharge_efficiency": 0.87,
                    "charge_efficiency": 0.87
                }
            ]
        }
    ]
}

CSV Format:

Typeidlocationdischarge_can_expanddischarge_can_retirestorage_can_expandstorage_can_retiredischarge_constraints–MinFlowConstraintdischarge_capacity_sizedischarge_existing_capacitydischarge_fixed_om_costdischarge_min_flow_fractiondischarge_efficiencycharge_efficiency
Batterypumpedhydro_SESEfalsefalsefalsefalsetrue2005000400000.50.870.87

Best Practices

  1. Use global data for common fields and 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 efficiencies: Make sure the efficiencies are realistic for the technology being modeled
  3. Use meaningful IDs: Choose descriptive identifiers that indicate location and technology type
  4. Consider duration constraints: Set appropriate min/max duration based on technology
  5. Use constraints selectively: Only enable constraints that are necessary for your modeling needs
  6. Validate costs: Ensure investment and O&M costs are in appropriate units
  7. Test configurations: Start with simple configurations and gradually add complexity

Input File (Advanced Format)

Macro provides an advanced format for defining battery 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 battery asset. The input file mirrors this hierarchical structure.

A battery asset in Macro is composed of a storage component, represented by a Storage object, and two edges (charge and discharge), each represented by an Edge object. The input file for a battery asset is therefore organized as follows:

{
    "storage":{
        // ... storage-specific attributes ...
    },
    "edges":{
        "charge_edge": {
            // ... charge_edge-specific attributes ...
        },
        "discharge_edge": {
            // ... discharge_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" or "charge_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 battery asset that sets up three batteries, located in the SE, MIDAT, and NE regions.

{
    "elec_stor": [
        {
            "type": "Battery",
            "global_data": {
                "storage": {
                    "commodity": "Electricity",
                    "can_expand": true,
                    "can_retire": false,
                    "constraints": {
                        "StorageMinDurationConstraint": true,
                        "StorageMaxDurationConstraint": true,
                    }
                },
                "edges": {
                    "discharge_edge": {
                        "type": "Electricity",
                        "unidirectional": true,
                        "has_capacity": true,
                        "can_expand": true,
                        "can_retire": false,
                        "constraints": {
                            "CapacityConstraint": true,
                            "StorageDischargeLimitConstraint": true
                        }
                    },
                    "charge_edge": {
                        "type": "Electricity",
                        "unidirectional": true,
                        "has_capacity": false
                    }
                }
            },
            "instance_data": [
                {
                    "id": "battery_SE",
                    "edges": {
                        "discharge_edge": {
                            "end_vertex": "elec_SE",
                            "capacity_size": 1.0,
                            "existing_capacity": 0.0,
                            "fixed_om_cost": 4536.98,
                            "investment_cost": 17239.56121,
                            "variable_om_cost": 0.15,
                            "efficiency": 0.92
                        },
                        "charge_edge": {
                            "start_vertex": "elec_SE",
                            "efficiency": 0.92,
                            "variable_om_cost": 0.15
                        }
                    },
                    "storage": {
                        "existing_capacity": 0.0,
                        "fixed_om_cost": 2541.19,
                        "investment_cost": 9656.002735,
                        "max_duration": 10,
                        "min_duration": 1
                    }
                },
                {
                    "id": "battery_MIDAT",
                    "edges": {
                        "discharge_edge": {
                            "end_vertex": "elec_SE",
                            "capacity_size": 1.0,
                            "existing_capacity": 0.0,
                            "fixed_om_cost": 4536.98,
                            "investment_cost": 17239.56121,
                            "variable_om_cost": 0.15,
                            "efficiency": 0.92
                        },
                        "charge_edge": {
                            "start_vertex": "elec_SE",
                            "efficiency": 0.92,
                            "variable_om_cost": 0.15
                        }
                    },
                    "storage": {
                        "existing_capacity": 0.0,
                        "fixed_om_cost": 2541.19,
                        "investment_cost": 9656.002735,
                        "max_duration": 10,
                        "min_duration": 1
                    }
                },
                {
                    "id": "battery_NE",
                    "edges": {
                        "discharge_edge": {
                            "end_vertex": "elec_SE",
                            "capacity_size": 1.0,
                            "existing_capacity": 0.0,
                            "fixed_om_cost": 4536.98,
                            "investment_cost": 17239.56121,
                            "variable_om_cost": 0.15,
                            "efficiency": 0.92
                        },
                        "charge_edge": {
                            "start_vertex": "elec_SE",
                            "efficiency": 0.92,
                            "variable_om_cost": 0.15
                        }
                    },
                    "storage": {
                        "existing_capacity": 0.0,
                        "fixed_om_cost": 2541.19,
                        "investment_cost": 9656.002735,
                        "max_duration": 10,
                        "min_duration": 1
                    }
                }
            ]
        }
    ]
}

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 charge and discharge edges are connected. These nodes must be defined in the nodes.json file.
  • 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.
The `has_capacity` Edge Attribute

The has_capacity attribute is a flag that indicates whether a specific edge of an asset has a capacity variable, allowing it to be expanded or retired. Typically, users do not need to manually adjust this flag, as the asset creators in Macro have already configured it correctly for each edge. However, advanced users can use this flag to override the default settings for each edge if needed.