Skip to content

Repository files navigation

Generic Flexibility Model

A Python framework for modeling and optimizing flexibility assets in energy systems from a utility company perspective.

Overview

This framework provides a clean, extensible architecture for evaluating the technical and economic potential of flexibility resources such as battery storage, photovoltaic systems, domestic hot water heaters, and other distributed energy resources (DERs).

The framework is designed to:

  • Separate concerns: Physical behavior, economic evaluation, and operational decisions are cleanly separated into distinct layers
  • Enable optimization: Provide interfaces that optimization algorithms can use to evaluate and execute operations
  • Support multiple assets: Generic base classes allow easy implementation of new flexibility assets
  • Facilitate learning: Clear architecture and comprehensive documentation make it suitable for teaching energy systems modeling

Key Use Cases

  • Evaluating flexibility potential for utility companies
  • Optimizing distributed energy resources (DERs) operation
  • Assessing techno-economic feasibility of flexibility services
  • Teaching energy systems modeling and optimization
  • Research on flexibility aggregation and market participation

Architecture

The framework uses a three-layer architecture that separates physical modeling from economic evaluation, joined by operational decision-making:

┌─────────────────────────────────────────────────────┐
│                   FlexAsset                         │
│            (Operational Composition)                │
│  • evaluate_operation() - Check feasibility & cost  │
│  • execute_operation() - Update state & track       │
└───────────────┬─────────────────┬───────────────────┘
                │                 │
       ┌────────▼────────┐   ┌────▼──────────┐
       │   FlexUnit      │   │  CostModel    │
       │   (Physics)     │   │  (Economics)  │
       │                 │   │               │
       │ • Power limits  │   │ • Investment  │
       │ • Efficiency    │   │ • Degradation │
       │ • State (SOC)   │   │ • Energy cost │
       │ • Constraints   │   │ • Revenues    │
       └─────────────────┘   └───────────────┘

Layer 1: FlexUnit (Physical/Technical Model)

Models the physical behavior of a flexibility asset:

  • Power limits and ramping constraints
  • Energy capacity and state of charge (SOC)
  • Efficiency characteristics (charging, discharging, conversion)
  • Self-discharge, standby losses, degradation
  • Availability and maintenance schedules

Key concept: Energy headroom representation

  • E_plus: Energy available to inject into the grid [kWh]
  • E_minus: Energy capacity available to draw from the grid [kWh]

Layer 2: CostModel (Economic Model)

Evaluates the economic implications of operations:

  • Investment costs (CAPEX)
  • Fixed and variable O&M costs
  • Degradation and cycling costs
  • Energy purchase and sales prices (time-varying)
  • Capacity reservation payments
  • Emissions costs (CO₂)

Layer 3: FlexAsset (Operational Interface)

Composes physics and economics to provide an operational interface:

  • evaluate_operation(): Check if an operation is feasible and calculate its cost
  • execute_operation(): Execute the operation and update system state
  • Tracks operational metrics (throughput, costs, activations)

This interface allows optimization algorithms to explore the solution space without needing to understand the internal physics or economics.


Current Implementation

✅ Battery Energy Storage System (BESS)

A complete implementation demonstrating all three layers:

  • BatteryUnit: Physical model with efficiency, SOC limits, power constraints, self-discharge
  • BatteryCostModel: Economic model with investment and degradation costs
  • BatteryFlex: Operational composition for feasibility checking and execution

Example:

from flex_model.assets import BatteryUnit, BatteryCostModel, BatteryFlex

# 1. Create physical model
battery_unit = BatteryUnit(
    name="BESS_100kWh",
    capacity_kwh=100.0,      # 100 kWh storage
    power_kw=50.0,           # 50 kW charge/discharge
    efficiency=0.95,         # 95% one-way efficiency
    soc_min=0.1,             # Don't discharge below 10%
    soc_max=0.9,             # Don't charge above 90%
)

# 2. Create economic model
battery_cost = BatteryCostModel(
    name="battery_economics",
    c_inv=500.0,              # 500 CHF/kWh investment
    n_lifetime=10.0,          # 10 year lifetime
    p_int=0.05,               # 0.05 CHF/kWh degradation cost
)

# 3. Compose operational interface
battery = BatteryFlex(unit=battery_unit, cost_model=battery_cost)

# 4. Initialize state (50% SOC)
battery.reset(E_plus_init=50.0, E_minus_init=50.0)

# 5. Evaluate operation (discharge 30 kW for 15 min)
result = battery.evaluate_operation(
    t=10,
    P_grid_import=0.0,
    P_grid_export=30.0
)

if result['feasible']:
    print(f"Operation cost: {result['cost']:.2f} CHF")
    print(f"SOC after: {result['soc']:.1%}")

    # 6. Execute if optimal
    battery.execute_operation(t=10, P_grid_import=0.0, P_grid_export=30.0)

🚧 Planned Implementations

  • Photovoltaic (PV): Solar generation with curtailment options
  • Domestic Hot Water (DHW): Thermal storage with temperature layers
  • Heat Pumps: Heating/cooling with COP modeling
  • Electric Vehicles (EV): Mobile storage with availability patterns

Installation

# Clone the repository
git clone https://github.com/yourusername/GenericFlexiblityModel.git
cd GenericFlexiblityModel

# Install in development mode
pip install -e .

# Run tests
pytest tests/ -v

Requirements

  • Python 3.10+
  • NumPy (for numerical operations)
  • pytest (for testing)

Project Structure

GenericFlexiblityModel/
├── flex_model/
│   ├── core/
│   │   ├── flex_unit.py      # Base class for physical models
│   │   ├── cost_model.py     # Base class for economic models
│   │   ├── flex_asset.py     # Base class for operational interface
│   │   └── access_state.py   # State management utilities
│   └── assets/
│       ├── battery.py        # Battery implementation (BatteryUnit, BatteryCostModel, BatteryFlex)
│       └── ...               # Future: PV, DHW, heat pumps, etc.
├── tests/
│   ├── test_battery.py       # Battery unit tests
│   └── ...
├── README.md
└── setup.py

Optimization Integration

The framework is designed to integrate with multiple optimization algorithms for finding optimal operation schedules. The FlexAsset interface provides two key methods:

  • evaluate_operation(): For optimization algorithms to query feasibility and costs without modifying state
  • execute_operation(): To apply the optimal solution and update system state

Optimization Workflow

  1. Optimizer proposes an operation (e.g., "charge battery at 30 kW")
  2. FlexAsset evaluates feasibility and calculates cost
  3. Optimizer explores solution space using its algorithm-specific approach
  4. Optimal operations are executed to update system state

Implemented Optimizers

✅ Linear Programming (LP)

Location: flex_model/optimization/lp_optimizer.py

Approach: Converts FlexAssets to LinearModel matrix representation and solves globally optimal solution using scipy's HiGHS solver.

Use cases:

  • Assets with linear constraints and costs (battery, market settlement)
  • Multi-asset coordination with global energy balance
  • Benchmark for optimal solutions

Limitations: Only handles convex, linear problems. Cannot model discrete decisions or non-linear relationships.

✅ Greedy Heuristic

Location: examples/battery_vs_market/greedy_optimizer.py

Approach: Time-sequential, rule-based decision making with threshold logic.

Use cases:

  • Fast approximate solutions
  • Real-time control where perfect foresight isn't available
  • Baseline comparison for more sophisticated methods

Limitations: Myopic (no future foresight), sub-optimal solutions.

Planned Optimizers

The framework is optimization-algorithm agnostic and designed to support:

🚧 Mixed-Integer Linear Programming (MILP)

Planned implementation: Extend LinearModel to support integer decision variables.

Use cases:

  • Discrete operating states (on/off decisions)
  • PV curtailment levels
  • Scheduling with binary availability constraints

Approach: Extends LP with integer variables, uses commercial solvers (Gurobi, CPLEX) or open-source (HiGHS with MILP support).

🚧 Dynamic Programming (DP)

Planned implementation: State-space representation with backward induction.

Use cases:

  • Sequential decision problems with state dependencies
  • Stochastic optimization (if extended to SDP)
  • Problems where Bellman optimality principle applies

Approach: Discretize state space (e.g., SOC levels), compute value function backward in time.

🚧 Genetic Algorithms (GA)

Planned implementation: Population-based evolutionary optimization.

Use cases:

  • Non-convex, non-linear objective functions
  • Complex constraints that don't fit LP/MILP formulations
  • Heat pumps with COP curves, thermal systems with stratification

Approach: Encode operation schedules as chromosomes, evolve through selection, crossover, and mutation.

🚧 Particle Swarm Optimization (PSO)

Planned implementation: Swarm intelligence approach.

Use cases:

  • Similar to GA, but often faster convergence
  • Continuous decision spaces
  • Multi-modal optimization landscapes

Approach: Particles explore solution space guided by personal and global best solutions.

🚧 Simulated Annealing (SA)

Planned implementation: Probabilistic single-solution metaheuristic.

Use cases:

  • Escaping local optima in non-convex problems
  • Faster than population methods for certain problem structures
  • When solution quality vs. computation time tradeoff is important

Approach: Random walk with probabilistic acceptance of worse solutions, cooling schedule.

🚧 Reinforcement Learning (RL)

Planned implementation: Learn optimal policies through interaction.

Use cases:

  • Unknown or uncertain system dynamics
  • Adaptive control that learns from operational data
  • Real-time optimization with prediction updates

Approach: Use evaluate_operation() as environment, learn Q-values or policy networks.

Choosing an Optimizer

Algorithm Speed Optimality Problem Types Maturity
LP Fast Globally optimal Linear, convex ✅ Implemented
Greedy Very fast Sub-optimal Any (heuristic) ✅ Implemented
MILP Medium Globally optimal Linear + discrete 🚧 Planned
DP Medium Globally optimal Sequential, discrete state 🚧 Planned
GA Slow Near-optimal Non-linear, non-convex 🚧 Planned
PSO Medium Near-optimal Non-linear, continuous 🚧 Planned
SA Medium Near-optimal Non-linear, non-convex 🚧 Planned
RL Slow (training) Near-optimal Unknown dynamics 🚧 Planned

Model Representations

Different optimization algorithms require different model representations. FlexAssets support multiple representations through dedicated methods:

  • Operational interface (evaluate_operation, execute_operation): Used by greedy, GA, PSO, SA, RL
  • Linear model (get_linear_model): Used by LP, MILP
  • State-space model (future: get_dp_model): Used by DP
  • Differentiable model (future: get_torch_model): Used by gradient-based RL

As new optimizers are implemented, corresponding representation methods will be added to FlexAsset classes. A model consistency test framework ensures all representations produce equivalent results.


Visualization Framework

The framework includes an interactive visualization toolkit for analyzing optimization results and supporting business decision-making.

Installation

Install visualization dependencies:

pip install -e .[visualization]
# or manually:
pip install plotly pandas

Key Components

OptimizationResult: Wrapper for optimizer outputs with convenient data extraction methods

  • get_power_profile() - Extract power dispatch time-series
  • get_soc_profile() - Extract state of charge evolution
  • get_cost_breakdown() - Parse cost components by asset
  • get_utilization_metrics() - Calculate capacity factors, cycle counts

EconomicMetrics: Calculator for financial KPIs

  • compute_roi() - Return on investment [%]
  • compute_payback_period() - Years to break even
  • compute_npv() - Net present value with discounting
  • compute_lcoe() - Levelized cost of energy
  • compute_financial_summary() - Complete KPI dashboard

Visualization Plots: Interactive Plotly visualizations

  • Operational: Power dispatch profiles, SOC evolution, price overlays
  • Economic: Cost breakdown, savings comparison, ROI gauges, payback timelines
  • Executive: Multi-panel financial dashboards

Example Usage

from flex_model.visualization import OptimizationResult, EconomicMetrics
from flex_model.visualization.plots import OperationalPlots, EconomicPlots

# Run optimization
result_dict = optimizer.solve()

# Wrap result
result = OptimizationResult(
    lp_result=result_dict,
    assets={'battery': battery, 'market': market},
    imbalance=imbalance_profile
)

# Generate visualizations
fig1 = OperationalPlots.create_dispatch_profile(result)
fig2 = OperationalPlots.create_soc_evolution(result, 'battery')
fig3 = EconomicPlots.create_savings_comparison(baseline_cost, optimized_cost)

# Display (in Jupyter) or save
fig1.show()
fig2.write_html('soc_evolution.html')

# Calculate economic metrics
financial_summary = EconomicMetrics.compute_financial_summary(
    result=result,
    baseline_cost=baseline_cost_annual,
    lifetime_years=10,
    discount_rate=0.05
)

print(f"ROI: {financial_summary['roi']:.1f}%")
print(f"Payback: {financial_summary['payback_period']:.1f} years")

Running the Example

See a complete demonstration in examples/battery_vs_market/visualize_results.py:

cd examples/battery_vs_market
python visualize_results.py

This generates 8 interactive HTML visualizations:

  1. Power dispatch profile (stacked area chart)
  2. SOC evolution with limits
  3. Price signals and market operations
  4. Cost breakdown by asset
  5. Savings vs baseline comparison
  6. ROI gauge with target benchmark
  7. Payback period timeline
  8. Comprehensive financial dashboard

Visualization Gallery

Power Dispatch Profile: Shows how imbalances are balanced across battery and market

  • Stacked area chart showing charge/discharge, import/export
  • Imbalance profile overlay for context
  • Toggle between system view and individual asset contributions

SOC Evolution: Battery state of charge with operating limits

  • Line chart with SOC bounds (min/max) as reference
  • Highlights constraint violations if any occur
  • Dual y-axis showing both % and absolute energy [kWh]

Economic Dashboard: Multi-panel KPI summary for executives

  • ROI gauge with color-coded targets
  • Payback period bar chart vs lifetime
  • Cost comparison (baseline vs optimized)
  • Key metrics table (NPV, LCOE, savings)

All visualizations are:

  • Interactive: Hover for details, zoom, pan, export images
  • Customizable: Plotly figures can be modified before saving
  • Business-focused: Designed for stakeholder communication
  • Web-ready: Export to standalone HTML files

Design Principles

  1. Separation of Concerns: Physics, economics, and operations are cleanly separated
  2. Composition over Inheritance: FlexAsset composes FlexUnit + CostModel
  3. Interface Segregation: Optimization algorithms only see evaluate/execute interface
  4. Time-Dependent Flexibility: All parameters can vary with time
  5. Educational Value: Clear documentation and examples for learning

Contributing

This is a research/educational project. Contributions are welcome:

  • New flexibility asset implementations
  • Optimization algorithm examples
  • Documentation improvements
  • Bug fixes and test coverage

License

This project is licensed under the MIT License - see the LICENSE file for details.


Citation

If you use this framework in your research, please cite:

[Add citation information when published]

Contact

Mathias Niffeler Urban Energy Systems Laboratory Empa, Dübendorf mathias.niffeler@empa.ch

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages