Electricity Supply Policies
Purpose
This section provides guidance for developers to create and maintain policy files that change electric generation inputs in ENERGY 2100. Covers file placement, coding pattern, common datasets to modify, examples, testing, and troubleshooting.
Types of Electric Utility Generation Policies
- Modify renewable generation goals
- Specify fixed amounts of energy transfers between areas through contracts
- Limit or increase flows and/or costs across transmission lines
- Activate offset requirements for generating units
- Modify characteristics of generating units (retirement year, outage rate, generating costs, etc.)
- Modify capacity expansion/build rules
- Modify characteristics of plant types as a whole (differentiated from individual units)
- Establish GHG performance goals
Where to put a policy file
- Folder: C:\2100ModelName\Policy
- Naming convention: Electric_<PolicyName>_<Region>.jl
- Add the file to a policy aggregator file (e.g. Ref25.jl) when ready
High‑level pattern (read → modify → write)
- Read sets/variables using ReadDisk (or Select helpers).
- Modify values in memory.
- Write changes back with WriteDisk.
Minimal policy file template
Key points:
- Import only required helpers: ReadDisk, WriteDisk, Select, etc.
- Create function to make changes to desired policy variables
- Create PolicyControl() function that calls policy changes
div class="html-code-box">
#
# Electric_[PolicyName]_[Region].jl
#
# Brief description of policy objectives and data sources
#
using EnergyModel
module [Policy_Electric_Template]
import ...EnergyModel: ReadDisk,WriteDisk,Select,Zero
import ...EnergyModel: HisTime,ITime,MaxTime,First,Future,Final,Yr
import ...EnergyModel: @finite_math
import ...EnergyModel: DB
const VariableArray{N} = Array{Float32,N} where {N}
const SetArray = Vector{String}
Base.@kwdef struct [Control]
db::String
#
# Define dimension sets
#
 Area::SetArray = ReadDisk(db,"MainDB/AreaKey")
Areas::Vector{Int} = collect(Select(Area))
 Unit::SetArray = ReadDisk(db,"MainDB/UnitKey")
 Units::Vector{Int} = collect(Select(Unit))
 Year::SetArray = ReadDisk(db,"MainDB/YearKey")
 Years::Vector{Int} = collect(Select(Year))
# ... other dimensions
# Load data variables:
 UnCode::Array{String} = ReadDisk(db,"EGInput/UnCode") # [Unit] Unit Code
 UnNode::Array{String} = ReadDisk(db,"EGInput/UnNode") # [Unit] Transmission Node
 UnOnLine::VariableArray{1} = ReadDisk(db,"EGInput/UnOnLine") # [Unit] On-Line Date (Year)
# ... other data as needed
end
function [PolicyName](db)
data = [Control](; db)
(; Unit,Units) = data
(; UnOnLine) = data
# TODO: apply transformations to policy variables using explicit indexing
end
end # module Policy_Electric_Template
unction PolicyControl(db)
@info("[PolicyName] PolicyControl function called")
[PolicyName](db) # Call to function that modifies the policy variable(s)
@info("Policy executed successfully")
end
if abspath(PROGRAM_FILE) == @__FILE__
PolicyControl(DB)
end
Common policy types & typical policy variables to modify
- Modify renewable generation goals
- EGInput/xGCPot, EGInput/PjMax (plant potentials / costs)
- Specify fixed energy transfers (contracts)
- EGInput/HDXLoad, EGInput/LLMax (contracted transfers / line capacity)
- Limit / increase flows or costs across transmission lines
- EGInput/LLMax (capacity)
- ECalDB/LineCost or ECalDB/PEDC if line costs are modeled there
- Activate offset requirements for generating units
- EGInput/OffRq, unit offset trackers
- Modify generating unit characteristics (retirement, outage, costs)
- EGInput/UnOnLine, EGInput/UnRetire, EGInput/UnEAF (availability/outage)
- Modify capacity expansion / build rules
- EGInput/xGCPot, EGInput/PjMax, plant potential
- Modify plant‑type characteristics (affect all units of a plant type)
- GCCCN, UOMC, UFOMC — map to Unit
- Establish GHG performance goals
- EGInput/UnPCFMax, EGInput/PCF (per‑unit or per‑plant carbon intensity)
- possibly set UnRetire where non‑compliant
Concrete examples (short)
- Set retirement year for a list of units
|
# # \Policy\Electric_SetRetireYears.jl # using EnergyModel module SetRetireYear import ...EnergyModel: ReadDisk,WriteDisk,Select,Zero import ...EnergyModel: HisTime,ITime,MaxTime,First,Future,Final,Yr import ...EnergyModel: @finite_math import ...EnergyModel: DB Base.@kwdef struct EControl db::String Unit::SetArray = ReadDisk(db,"MainDB/UnitKey") Units::Vector{Int} = collect(Select(Unit)) Year::SetArray = ReadDisk(db,"MainDB/YearKey") Years::Vector{Int} = collect(Select(Year))
UnArea::Array{String} = ReadDisk(db,"EGInput/UnArea") # [Unit] Area Pointer UnCode::Array{String} = ReadDisk(db,"EGInput/UnCode") # [Unit] Unit Code UnRetire::VariableArray{2} = ReadDisk(db,"EGInput/UnRetire") # [Unit,Year] Retirement Date (Year) end function ElectricPolicy(db) data = EControl(; db) (; Units,Years) = data (; UnCode,UnRetire) = data for unit in Units if UnCode[unit] == "AB00002000101" for year in Years UnRetire[unit,year] = 2050 end end if UnCode[unit] == "AB00002000300" for year in Years UnRetire[unit,year] = 2050 end end end WriteDisk(DB, "EGInput/UnRetire",UnRetire) end function PolicyControl(db) @info "Electric_SetRetirementYears.jl - PolicyControl" ElectricPolicy(db) end
if abspath(PROGRAM_FILE) == @__FILE__ PolicyControl(DB) end end end # module |
- Modify a transmission line capacity example (pseudo)
|
# # \Policy\Electric_ModifyLineCapacity.jl # using EnergyModel module ModifyLineCapacity import ...EnergyModel: ReadDisk,WriteDisk,Select,Zero import ...EnergyModel: HisTime,ITime,MaxTime,First,Future,Final,Yr import ...EnergyModel: @finite_math import ...EnergyModel: DB Base.@kwdef struct EControl db::String Node::SetArray = ReadDisk(db,"MainDB/NodeKey") Nodes::Vector{Int} = collect(Select(Node)) NodeX::SetArray = ReadDisk(db,"MainDB/NodeXKey") NodeXs::Vector{Int} = collect(Select(NodeX)) TimeP::SetArray = ReadDisk(db,"MainDB/TimePKey") TimePs::Vector{Int} = collect(Select(TimeP)) Year::SetArray = ReadDisk(db,"MainDB/YearKey") Years::Vector{Int} = collect(Select(Year))
LLMax::VariableArray{5} = ReadDisk(db,"EGInput/LLMax") # [Node,NodeX,TimeP,Month,Year] Maximum Loading on Transmission Lines (MW) end function ElectricPolicy(db) data = EControl(; db) (; Units,Years) = data (; UnCode,UnRetire) = data # # New line capacity to Ontario (ON) from Pennsylvania (PJME) # node = Select(Node,"ON") # To Node nodex = Select(NodeX,"PJME") # From NodeX years = collect(Yr(2030):Final) for year in years, month in Months, timep in TimePs LLMax[node,nodex,timep,month,year] = 1000 end # # New line capacity from Ontario (ON) to Pennsylvania (PJME) # node = Select(Node,"PJME") # To Node nodex = Select(NodeX,"ON") # From NodeX years = collect(Yr(2030):Final) for year in years, month in Months, timep in TimePs LLMax[node,nodex,timep,month,year] = 1000 end # # Write LLMax to database # WriteDisk(db,"EGInput/LLMax",LLMax) end function PolicyControl(db) @info "Electric_SetRetirementYears.jl - PolicyControl" ElectricPolicy(db) end
if abspath(PROGRAM_FILE) == @__FILE__ PolicyControl(DB) end end end # module |
Testing policy files
From Julia REPL:
|
julia> import EnergyModel: DB julia> include("\Policy\Electric_SetRetireYears.jl") julia> Electric_SetRetireYears.PolicyControl(DB) |
What happens when a policy changes DB variables
- Policies modify EGInput (and possibly ECalDB/EGOutput) datasets in the HDF5.
- Model initialization and engine modules (dispatch, capacity expansion, flows) read these datasets at run start and use modified values during simulation.
Documentation & header conventions
Top of file should include:
- Purpose and description
- Inputs: list of required datasets (exact HDF5 paths)
- Outputs: datasets modified
- External dependencies (e.g., NextGrid files)
- Author, date, scenario tag
Checklist before committing
- [ ] Test running individual policy and verify policy variables changed as intended
- [ ] Add header documentation and usage instructions in the file
- [ ] Add to Ref25.jl or policy aggregator only when ready