Architecture
Component Overview
Simulation Request Lifecycle
- API receives
POST /simulatewithparams+runconfig - Data loading — ScenarioManager retrieves price/solar/aFRR/FCR data from cache or SQLite
- Profile loading — If
profile_idorwind_profile_idset, ProfileManager retrieves production data - Initialization — BESSSimulator creates BatteryModel, DegradationModel, SolarModel, WindModel
- Data alignment — Price and profile timeseries aligned to 15-min intervals starting at
startProject - Optimization — MultiMarketOptimizer runs selected strategy over price data
- Degradation tracking — SimpleDegradationTracker updates battery state periodically (~weekly)
- Generation calculation — Solar/wind models compute generation and subsidy revenue
- Output — OutputHandler computes financial metrics and formats timeseries
- Response — JSON returned with summary, optional timeseries, optional yearly summaries
Database Design
The system uses a split database pattern to separate lightweight metadata from heavy timeseries data.
Metadata Databases
db/scenarios.db — scenario metadata:
| Column | Type | Description |
|---|---|---|
id | INTEGER PK AUTOINCREMENT | Scenario ID |
name | TEXT | Scenario name |
country | TEXT | Country code |
description | TEXT | Description |
preload | BOOLEAN | Auto-load to cache on startup |
has_price_data | BOOLEAN | Price data imported |
has_solar_data | BOOLEAN | Solar data imported |
has_afrr_data | BOOLEAN | aFRR data imported |
has_fcr_data | BOOLEAN | FCR data imported |
record_count | INTEGER | Number of records |
db/profiles.db — profile metadata:
| Column | Type | Description |
|---|---|---|
id | TEXT PK | UUID (prevents ID reuse on DB recreation) |
name | TEXT | Profile name |
profile_type | TEXT | pv or wind |
source_type | TEXT | generated or imported |
latitude | REAL | Location |
longitude | REAL | Location |
capacity_mw | REAL | Installed capacity |
config | TEXT (JSON) | Generation configuration |
preload | BOOLEAN | Auto-load to cache |
Per-Entity Data Databases
Each scenario and profile gets its own SQLite database file:
db/scenario_data/scenario_{id}.db— price, aFRR, FCR, solar, and installed capacity tablesdb/profile_data/profile_{uuid}.db— production timeseries and monthly statistics
Why Split?
- Metadata queries stay fast — small DB, frequently queried for listings
- Timeseries data is isolated — no single-DB bottleneck
- Clean deletion — removing an entity = dropping a file
- Independent caching — each entity can be cached or uncached separately
Caching
Both ScenarioManager and ProfileManager maintain in-memory caches:
| Property | Detail |
|---|---|
| Storage | NumPy arrays for timeseries, Pydantic models for metadata |
| Preload | Entities with preload=True loaded on API startup |
| Manual control | POST /{type}/{id}/cache/load and /cache/unload |
| Thread safety | Python RLock for concurrent access |
| Memory limit | Configurable (default 1000 MB total) |
| Monitoring | GET /{type}/cache/stats reports cached count and memory |
Multi-Year Execution
Sequential Mode (default)
Battery state carries between years. Degradation is continuous and accurate.
Parallel Mode (parallel_years=True)
Each year runs independently in a separate process, starting at 50% SOC. Degradation is estimated per year based on expected cycling. Faster but less accurate — no inter-year state carry-over.
Worker count is controlled by the SIMULATION_WORKERS environment variable (default: CPU count).
Source Files
| File | Purpose |
|---|---|
api.py | FastAPI REST API (~1400 lines) |
bess_engine/simulator.py | Main simulation orchestrator |
bess_engine/optimizer.py | Multi-market LP optimization engine |
bess_engine/battery_model.py | Battery physics & SoC tracking |
bess_engine/degradation.py | Cycle + calendar degradation models |
bess_engine/input_handler.py | Input validation & parsing |
bess_engine/output_handler.py | Results formatting & financial calcs |
bess_engine/solar_model.py | Solar PV generation model |
bess_engine/wind_model.py | Wind generation model |
bess_engine/scenario_manager/ | Market price data management |
bess_engine/profile_manager/ | Solar/wind production profiles |