A Python-based power grid optimization framework for modeling energy systems with renewable integration and policy constraints.
- Status & Roadmap
- Prerequisites
- Installation
- Running the Network
- Project Structure
- Optimization Framework
- Testing
- Current State: Development
- Key Features:
- Power grid network modeling
- Renewable integration optimization
- Policy constraint handling
- Multi-region transmission modeling
- Policy implementation from graph data (see network.py TODO)
- Improved data validation for input files
- Documentation for data file formats
- Unit test coverage
- Performance optimization for large networks
- Python 3.8+
- pip
- (optional) Jupyter Notebook
- Clone the repository:
git clone <repository-url>
cd <repository-name>
- Create and activate a virtual environment (recommended):
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
- Install dependencies:
pip install -r requirements.txt
- Configure your settings in
config.py
:
# Edit regions of interest
REGIONS = ['ERC_FRNT', 'ERC_PHDL', 'ERC_REST', 'ERC_WEST']
# Adjust time window
START_HOUR = 0 # Start hour of the year (0-8759)
NUM_HOURS = 24 # Number of hours to optimize
# Modify paths if needed
INPUT_GRAPH_PATH = 'Data/Default/US/graph.json'
- Run the optimization:
python run_network.py
- Check the outputs:
- Results will be saved to
optimization_results.json
(configurable in config.py) - Logs will be written to
optimization_output.log
- Enable DEBUG_MODE in config.py for additional output
The config.py
file allows you to customize:
- Regions: Which geographical areas to include
- Time Window: Start time and duration of optimization
- Network Parameters: Line efficiency and other technical parameters
- Input/Output: File paths for data, logs, and results
- Debug Settings: Toggle detailed debug output
# Load a pre-built graph
graph = graph_from_json('Data/Default/US/graph.json')
# Create a subgraph for specific regions
regions = ['ERC_FRNT', 'ERC_PHDL', 'ERC_REST', 'ERC_WEST']
sub_g = subgraph(graph, regions)
# Create optimization network
network = Network()
network.add_plants(plants) # Add plant data
# Define time window
time_steps = range(24) # 24-hour optimization
# Create and solve optimization
opt_model = OptimizationModel(network, time_steps)
results = opt_model.solve()
src/
: Core source codeoptimization/
: Optimization model componentsnetwork.py
: Core class managing the optimization network structure- Uses NetworkX's
DiGraph
to represent the power grid - Handles nodes (regions, policies) and edges (transmission lines)
- Manages policies and plant assignments
- Uses NetworkX's
base/
andbuses/
:Region
: Represents geographical areas containing assetsPolicy
: Handles renewable requirements for different jurisdictions
assets/
:Producer
: Power plants with capacity, costs, emissionsStore
: Energy storage facilitiesLoad
: Power demand centersLine
: Transmission lines connecting regions
model.py
:- Uses Pyomo for optimization
- Defines variables, constraints, and objective function components for each asset type
graph/
: Network graph handlinginputs/
: Data processing utilities
Data/
: Input data files
- Region: Represents geographical areas containing assets.
- Policy: Handles renewable requirements for different jurisdictions.
Each node can contain multiple assets:
- Producers (e.g., power plants)
- Loads (e.g., power demand centers)
- Storage facilities (e.g., batteries)
- Producer: Represents power plants with attributes like capacity, costs, and emissions.
- Store: Represents energy storage facilities.
- Load: Represents centers of power demand.
- Line: Represents transmission lines connecting regions.
The framework uses Pyomo for optimization. Each asset type defines:
- Variables (e.g., production levels, storage levels).
- Constraints (e.g., capacity limits, renewable requirements).
- Objective function components (e.g., costs).
The system is modular:
- Each component (region, plant, line) defines its own optimization variables and constraints.
- The
Network
class orchestrates interactions between components. - Policies act as cross-cutting concerns, adding constraints across multiple assets.
The project uses pytest for testing. Tests are organized into:
- Feasibility tests (
test_feasibility.py
): Basic network operation - Edge case tests (
test_edge_cases.py
): Boundary conditions and error cases
Run all tests:
pytest
Run specific test categories:
pytest -v -m optimization # Run optimization-related tests
pytest tests/test_feasibility.py # Run feasibility tests only
Tests use fixture data defined in conftest.py
to create test networks:
# Example test using fixtures
def test_empty_network(self, empty_graph):
"""Test that empty network has zero generation and cost"""
network = Network().set_graph(graph_from_dict(empty_graph))
result = network.optimize()
assert result.objective_value == 0
Common test scenarios are provided as fixtures:
empty_graph
: Empty network with no nodes or edgessingle_node_graph
: Single region with generator and loadtwo_node_graph
: Two connected regions with transmission
- Use the provided fixtures or create new ones in
conftest.py
- Create network using the
Network().set_graph()
pattern:
network = Network().set_graph(graph_from_dict(test_graph))
- Add appropriate assertions:
# Test generation matches load
assert sum(gen.production for gen in result.generators.values()) == total_load
# Test transmission limits
assert result.lines["line1"].flow <= line_capacity
- Add markers for test categorization:
@pytest.mark.optimization
def test_my_feature():
...
optimization_results.json
: Optimization results.optimization_output.log
: Detailed logging output.