FLEX-Community

What It Does

FLEX-Community takes the reference mode operation results from a group of households and models how an energy community aggregator can generate profit by coordinating them. It does not re-run household simulation — it works entirely on top of precomputed hourly household profiles.

The model iterates over community scenario IDs. Each scenario defines a different aggregator configuration (e.g., different battery sizes), applied to the same fixed set of household operation results.

Two Profit Mechanisms

These are fundamentally different in their logic and are computed separately:

1. P2P Trading Profit (Rule-Based)

The aggregator facilitates peer-to-peer electricity trading within the community in real time. When one household has PV surplus and another has a load deficit at the same hour, the aggregator routes electricity between them instead of letting it flow to and from the grid.

The calculation is purely arithmetic — no optimization involved:

\[\text{PV}_{\text{comm},t} = \sum_{h} \text{PV}_{h,t}\]
\[\text{Load}_{\text{comm},t} = \sum_{h} \text{Load}_{h,t}\]
\[\text{PV}^{\text{consumed}}_t = \min\!\left(\text{PV}_{\text{comm},t},\; \text{Load}_{\text{comm},t}\right)\]
\[\text{PV}^{\text{self}}_t = \sum_{h} \min\!\left(\text{PV}_{h,t},\; \text{Load}_{h,t}\right)\]
\[\text{P2P}_t = \text{PV}^{\text{consumed}}_t - \text{PV}^{\text{self}}_t\]

The P2P profit comes from the spread between what the aggregator charges households for community electricity (a fraction of the retail price) and what it pays them for their surplus PV (a fraction of the feed-in tariff). The buy/sell price factors are scenario parameters (aggregator_buy_price_factor, aggregator_sell_price_factor).

This calculation is in src/models/community/scenario.py.

2. Aggregator Battery Optimization Profit (LP)

The aggregator operates a battery — either its own dedicated battery or, optionally, the combined capacity of household batteries — to buy electricity cheaply and sell it at higher prices (arbitrage).

This is a Pyomo LP solved in src/models/community/model.py:

  • Objective:

\[\max \sum_{t=1}^{8760} \left( d_t \cdot \eta_{\text{dis}} \cdot p^{\text{sell}}_t \;-\; c_t \cdot p^{\text{buy}}_t \right)\]
  • Where \(p^{\text{buy}}_t = \lambda^{\text{FiT}}_t \cdot f_{\text{buy}}\) and \(p^{\text{sell}}_t = \lambda^{\text{elec}}_t \cdot f_{\text{sell}}\)

  • Constraints: battery SoC dynamics, charge/discharge power limits, SoC upper bound

The SoC upper bound depends on the aggregator_household_battery_control flag:

  • ctrl = 0: aggregator operates only its own dedicated battery.

  • ctrl = 1: aggregator also controls household batteries — available capacity is the aggregator battery plus the unused capacity across all household batteries (battery_capacity household_BatSoC).

Inputs

The community model reads operation results that have been pre-exported into community input tables (the projects/test_community/main.py helper function copy_operation_tables handles this):

Table

Content

CommunityScenario

Community scenario parameters (battery size, price factors, control mode)

CommunityScenario_OperationScenario

Operation scenario table copied from FLEX-Operation input

CommunityScenario_Household_RefHour

Hourly Ref results for all household scenarios: PhotovoltaicProfile, Grid, Load, Feed2Grid, BatSoC

CommunityScenario_Household_RefYear

Annual Ref results: TotalCost per household scenario

CommunityScenario_EnergyPrice

Community-level electricity and feed-in price time series

CommunityScenario_Component_Battery

Battery capacity table (maps ID_Battery to capacity in Wh)

Outputs

Table

Resolution

Key columns

CommunityResult_AggregatorHour

Hourly, per community scenario

p2p_trading, battery_charge, battery_discharge, battery_soc, buy_price, sell_price

CommunityResult_AggregatorYear

Annual, per community scenario

p2p_profit, opt_profit, total_profit

Key Code Locations

File

Role

src/models/community/main.py

Entry point — run_community_model()

src/models/community/scenario.py

Community scenario setup; P2P trading calculation

src/models/community/model.py

Aggregator LP: configures parameters, solves, extracts result

src/models/community/aggregator.py

Pyomo model definition: sets, variables, constraints, objective

src/models/community/household.py

Maps operation result rows to per-household objects

src/models/community/data_collector.py

Collects hourly and annual results and writes to output

How to Run

The community model depends on FLEX-Operation outputs. The typical workflow:

# 1. Run operation model to generate household results
python -m projects.test_operation.main

# 2. Copy operation results into community input format
#    (handled automatically by test_community/main.py)

# 3. Run community model
python -m projects.test_community.main

Output is written to projects/test_community/output/.