CITADEL Critical Infrastructure Simulator
Project description
CITADEL Grid Simulator
A pandapower-based electrical grid simulation system with DERs (Distributed Energy Resources) for cybersecurity and zero-trust policy research. The simulator acts as SCADA substations/RTUs communicating via DNP3 and Modbus protocols.
Overview
The CITADEL Grid Simulator provides realistic power grid simulation capabilities for research and testing:
- Modern Grid Model: Dickert LV distribution network with DER support
- Real-time Simulation: 1-second timestep power flow calculations
- SCADA Protocols: DNP3 outstation and Modbus server interfaces
- Time-Series Data: Realistic load, solar PV, and wind generation profiles
- Zero-Trust Ready: Control points for policy enforcement on breakers, loads, and DERs
- Thread-Safe: Concurrent operation with command queue and state callbacks
Installation
# Using micromamba (recommended)
micromamba env create -f environment.yml
micromamba activate grid-simulator
# Or using conda
conda env create -f environment.yml
conda activate grid-simulator
Configuration
# Copy example config
cp src/settingslocal.py.example src/settingslocal.py
# Edit configuration as needed
nano src/settingslocal.py
Running the Simulator
# Using Makefile
make run
# Or directly
cd src && python -m main
# Or using the installed command
citadel-simulator
Grid Models
The simulator provides an extensible framework for power grid modeling. The default implementation uses the Dickert LV distribution network model, but the architecture supports custom grid models.
Default Model: Dickert LV Network
The included Dickert LV model is specifically designed for DER research and serves as a reference implementation:
- DER-focused: Designed for distribution-level DER integration studies
- Modern architecture: Reflects current grids with high DER penetration
- Zero-trust suitable: Smaller scale ideal for cyber/control experimentation
- Realistic topology: Includes residential/commercial loads, solar PV, storage
- Manageable scale: Rapid iteration for policy enforcement scenarios
Network Classes:
- Class 1: Smallest network (default)
- Class 2-5: Increasing size and complexity
Custom Grid Models
The simulator architecture is designed to be model-agnostic. You can implement custom grid models by:
- Creating a new model class in
src/models/ - Implementing the required pandapower network structure
- Registering the model in the configuration
See src/models/dickert_lv.py for a reference implementation.
Reference
@inproceedings{dickert2013,
author = {Dickert, Jörg and Domagk, Max and Schegner, Peter},
year = {2013},
month = {06},
title = {Benchmark Low Voltage Distribution Networks Based on Cluster Analysis of Actual Grid Properties},
doi = {10.1109/PTC.2013.6652250}
}
SCADA Protocols
DNP3 Outstation
Port: 20000 (configurable)
Point Mapping:
- Analog Inputs 0-N: Bus voltages (per unit)
- Analog Inputs 100+: Line power flows (MW)
- Analog Inputs 200+: DER generation (MW)
- Binary Inputs 0-N: Breaker status (open/closed)
- Binary Outputs 0-N: Breaker controls
Features:
- Integrity polls
- Event reporting
- Control operations
- Quality flags
- Timestamps
Modbus Server
Port: 502 (configurable)
Register Mapping:
- Holding Registers 0-999: Bus voltages (scaled)
- Holding Registers 1000-1999: Line flows (scaled)
- Holding Registers 2000-2999: DER generation (scaled)
- Coils 0-999: Breaker status
- Coils 1000-1999: Breaker controls
Features:
- Function codes: 1, 2, 3, 4, 5, 6, 15, 16
- Exception handling
- Multiple client support
SCADA Commands
The simulator supports the following control commands:
OPEN_BREAKER- Open a line breakerCLOSE_BREAKER- Close a line breakerSET_DER_SETPOINT- Adjust DER power outputADJUST_LOAD- Modify load demandSET_STORAGE_POWER- Control energy storage (charge/discharge)
Configuration
Environment Variables
# Simulation
SIMULATION_TIMESTEP=1.0 # seconds
NETWORK_CLASS=1 # Dickert LV network class (1-5)
NUM_TRANSFORMERS=1 # Number of transformers (1-2)
# DNP3
DNP3_ENABLED=true
DNP3_PORT=20000
DNP3_LOCAL_ADDRESS=1
DNP3_REMOTE_ADDRESS=10
# Modbus
MODBUS_ENABLED=true
MODBUS_PORT=502
MODBUS_UNIT_ID=1
# Logging
LOG_LEVEL=INFO
LOG_FILE=grid_simulator.log
Settings File
See src/settingslocal.py.example for all configuration options.
Time-Series Data Generation
The simulator includes comprehensive time-series generators for realistic load and generation profiles.
Load Profiles
Residential:
- Morning peak: 6-9 AM
- Evening peak: 5-10 PM
- Overnight minimum: 11 PM - 5 AM
- Seasonal variations (summer AC, winter heating)
- Weekday/weekend differences
- Stochastic noise (15%)
Commercial:
- Office: 8 AM - 6 PM weekdays
- Retail: 9 AM - 9 PM daily
- Industrial: 24/7 operation
- Stochastic noise (10%)
Solar PV Profiles
- Cosine irradiance curve (sunrise to sunset)
- Seasonal sun angle variations
- Cloud effects: clear, partly cloudy, cloudy
- Inverter efficiency (96% default)
- Day-to-day variability
Wind Profiles
- Power curve: cut-in 3 m/s, rated 12 m/s, cut-out 25 m/s
- AR(1) process for temporal correlation
- Cubic power relationship
- Stochastic variations
Example Usage
from timeseries import LoadProfileGenerator, SolarProfileGenerator
# Generate load profiles
load_gen = LoadProfileGenerator(random_seed=42)
loads = load_gen.generate_multiple_loads(
num_residential=5,
num_commercial=2,
num_days=7,
season='summer'
)
# Generate solar profiles
solar_gen = SolarProfileGenerator(random_seed=42)
solar = solar_gen.generate_with_variability(
num_days=7,
rated_capacity_kw=10.0,
season='summer'
)
# Convert to pandapower format
load_pp = load_gen.to_pandapower_format(loads, load_indices)
solar_pp = solar_gen.to_pandapower_format(solar, sgen_indices)
Development
Makefile Commands
make help # Show available commands
make install # Create conda environment
make test # Run tests
make run # Run simulator
make clean # Remove generated files
make lint # Run linting
make format # Format code
Testing
# Run all tests
make test
# Run specific test file
python -m pytest src/tests/test_basic.py -v
# Run with coverage
python -m pytest --cov=src src/tests/
SCADA Client Testing
# Test with Modbus client
mbpoll -a 1 -r 0 -c 10 localhost
# Test with DNP3 client
# (Use dnp3demo or similar DNP3 master tool)
Performance
- Timestep: 1 second (configurable)
- State history: 3600 steps (1 hour at 1s timestep)
- Protocol updates: On every timestep
- Typical CPU: <5% for Class 1 network
- Memory: ~100MB for Class 1 network
Troubleshooting
Common Issues
Power flow doesn't converge:
- Check load/generation balance
- Verify network connectivity
- Review voltage limits
DNP3 connection fails:
- Check port 20000 is not in use
- Verify firewall settings
- Check DNP3 addresses match
Modbus connection fails:
- Check port 502 is not in use (may need sudo)
- Verify unit ID matches
- Check register addresses
Debug Mode
# Enable debug logging
export LOG_LEVEL=DEBUG
python -m src.main
License
See LICENSE file for details.
References
Acknowledgments
This software was developed under U.S. Department of Energy award DE-CR0000049, issued by the Office of Cybersecurity, Energy Security, and Emergency Response (CESER). The prime contractor on this work was Iowa State University, and the ideas herein are influenced by conversations with them. The submitted manuscript has been created by UChicago Argonne, LLC, operator of Argonne National Laboratory. Argonne, a DOE Office of Science laboratory, is operated under Contract No. DE-AC02-06CH11357. The U.S. Government retains for itself, and others acting on its behalf, a paid-up nonexclusive, irrevocable worldwide license in said article to reproduce, prepare derivative works, distribute copies to the public, and perform publicly and display publicly, by or on behalf of the Government.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file citadel_simulator-1.0.5.tar.gz.
File metadata
- Download URL: citadel_simulator-1.0.5.tar.gz
- Upload date:
- Size: 69.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc6c0988d72f58b32c6738b703c651bb56f23cfb902c230fec5f7b466b4acc14
|
|
| MD5 |
b94a937a6db3a68f2a1761fe19d1e80d
|
|
| BLAKE2b-256 |
b9c78a3273d7b42e505a67c1bd82aa845501b8a730df3530700feb7fc996bed2
|
File details
Details for the file citadel_simulator-1.0.5-py3-none-any.whl.
File metadata
- Download URL: citadel_simulator-1.0.5-py3-none-any.whl
- Upload date:
- Size: 83.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9741f9fb8a122395bdcc2c326996d708fbe23405960b2f1aca347e09a3f60064
|
|
| MD5 |
bdead3a08abfa55f199fd93232bd1479
|
|
| BLAKE2b-256 |
4748480ba1f84510c5bf42814465de925dfce7d46ead69da01fc3dc1bebb9d96
|