335 lines
8.3 KiB
Markdown
335 lines
8.3 KiB
Markdown
# ☀️ cyberbee PV Simulator
|
|
|
|
A modular, realistic photovoltaic plant simulator written in Python.
|
|
|
|
cyberbee PV Simulator generates synthetic time-series data for an entire PV plant hierarchy — from individual panels up to the plant level — with physically grounded models, configurable fault injection, and multi-format export.
|
|
|
|
---
|
|
|
|
## Features
|
|
|
|
**Physical modelling**
|
|
- Solar position computed via `pvlib` (elevation, azimuth, zenith, angle of incidence)
|
|
- Clear-sky irradiance with seasonal and daily variation (GHI, DNI, DHI, POA)
|
|
- Module temperature model (simplified NOCT approach)
|
|
- Temperature coefficient applied to power output
|
|
- Annual degradation of panels
|
|
- Sensor noise (Gaussian)
|
|
|
|
**Fault simulation**
|
|
- Panel failure, soiling, and partial shading
|
|
- Combiner box offline
|
|
- Inverter shutdown
|
|
- Configurable daily failure probabilities per component level
|
|
- Fault severity and reduction factors
|
|
|
|
**Weather**
|
|
- Configurable cloud factor with random variability
|
|
- Rain events with daily probability
|
|
- Ambient temperature (annual mean + daily swing)
|
|
|
|
**Hierarchical aggregation**
|
|
|
|
```
|
|
PV Plant
|
|
├── Inverter 1
|
|
│ ├── Combiner Box 1
|
|
│ │ ├── String 1 → Panel 1 … Panel 20
|
|
│ │ └── String 2 → Panel 1 … Panel 20
|
|
│ └── Combiner Box 2
|
|
│ └── ...
|
|
└── Inverter 2
|
|
└── ...
|
|
```
|
|
|
|
**Output & export**
|
|
- CSV, Parquet, JSON, SQLite
|
|
- Per-component time series (panel, combiner, inverter, plant, weather, faults)
|
|
- KPI and statistics: energy yield, performance ratio, availability, specific yield, clipping losses, daily/monthly aggregations, fault summaries
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
pv_simulator/
|
|
│
|
|
├── config/
|
|
│ └── plant.json # Plant configuration
|
|
│
|
|
├── pvsim/
|
|
│ ├── __init__.py
|
|
│ ├── panel.py # PVPanel model
|
|
│ ├── combiner.py # CombinerBox model
|
|
│ ├── inverter.py # Inverter model
|
|
│ ├── plant.py # PVPlant (top-level object)
|
|
│ ├── sun.py # Solar position model (pvlib)
|
|
│ ├── weather.py # Meteorological model
|
|
│ ├── faults.py # Fault manager and fault types
|
|
│ ├── simulator.py # Simulation engine (PVSimulator)
|
|
│ ├── exporter.py # CSV / Parquet / JSON export
|
|
│ ├── statistics.py # KPI and statistics
|
|
│ └── utils.py # Shared utilities
|
|
│
|
|
├── output/ # Generated data (auto-created)
|
|
│
|
|
├── run.py # Entry point
|
|
├── requirements.txt
|
|
└── README.md
|
|
```
|
|
|
|
---
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
git clone https://github.com/your-username/pv-simulator.git
|
|
cd pv-simulator
|
|
|
|
python -m venv .venv
|
|
source .venv/bin/activate # Linux / macOS
|
|
# .venv\Scripts\activate # Windows
|
|
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
**Requirements**
|
|
|
|
| Library | Purpose |
|
|
|---|---|
|
|
| `numpy` | Numerical computations |
|
|
| `pandas` | Time-series management, CSV/Parquet export |
|
|
| `matplotlib` | Production charts |
|
|
| `scipy` | Statistical distributions and realistic noise |
|
|
| `pvlib` | Solar position, irradiance models, PV physics |
|
|
| `networkx` | Plant hierarchy representation |
|
|
| `pyyaml` | YAML configuration support |
|
|
| `tqdm` | Progress bar for long simulations |
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
The entire plant is described in `pv_simulator/config/plant.json`. No code changes are needed to resize or reconfigure the plant.
|
|
|
|
```json
|
|
{
|
|
"plant": {
|
|
"name": "ZAK_PV_Simulator",
|
|
"location": {
|
|
"latitude": 45.4642,
|
|
"longitude": 9.1900,
|
|
"timezone": "Europe/Rome",
|
|
"altitude": 120
|
|
},
|
|
"simulation": {
|
|
"time_resolution_minutes": 5,
|
|
"start_date": "2026-01-01 00:00:00",
|
|
"end_date": "2026-12-31 23:55:00"
|
|
}
|
|
},
|
|
"layout": {
|
|
"inverters": [
|
|
{
|
|
"id": "INV_001",
|
|
"nominal_power_kW": 100,
|
|
"combiners": [
|
|
{
|
|
"id": "CB_001",
|
|
"strings": 4,
|
|
"panels_per_string": 20,
|
|
"orientation": { "tilt_deg": 30, "azimuth_deg": 180 }
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
The default configuration generates:
|
|
|
|
| Component | Count |
|
|
|---|---|
|
|
| Inverters | 2 |
|
|
| Combiner boxes | 3 |
|
|
| Panels | 240 |
|
|
| Nominal DC power | 108 kWp |
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
### Run a full simulation
|
|
|
|
```python
|
|
from datetime import datetime
|
|
from pvsim.simulator import PVSimulator, SimulationConfig
|
|
from pvsim.exporter import SimulationExporter
|
|
from pvsim.statistics import SimulationStatistics
|
|
|
|
config = SimulationConfig(
|
|
start=datetime(2026, 6, 21),
|
|
end=datetime(2026, 6, 22),
|
|
timestep_minutes=5,
|
|
generate_random_faults=True,
|
|
)
|
|
|
|
result = simulator.run(config)
|
|
```
|
|
|
|
### Compute KPIs
|
|
|
|
```python
|
|
stats = SimulationStatistics(result)
|
|
kpi = stats.plant_kpi()
|
|
|
|
print(f"Energy produced : {kpi.energy_kWh:.1f} kWh")
|
|
print(f"Peak power : {kpi.peak_power_W:.0f} W")
|
|
print(f"Performance ratio: {kpi.performance_ratio:.2%}")
|
|
print(f"Availability : {kpi.availability:.2%}")
|
|
```
|
|
|
|
### Export data
|
|
|
|
```python
|
|
exporter = SimulationExporter(output_dir="output")
|
|
exporter.export_all(result, csv=True, parquet=True, json=True, statistics=True)
|
|
```
|
|
|
|
---
|
|
|
|
## Output Structure
|
|
|
|
```
|
|
output/
|
|
│
|
|
├── simulation.json # Simulation summary
|
|
├── plant_kpi.json # Plant-level KPIs
|
|
│
|
|
├── panel_kpi.csv
|
|
├── combiner_kpi.csv
|
|
├── inverter_kpi.csv
|
|
├── daily_statistics.csv
|
|
├── monthly_statistics.csv
|
|
├── fault_summary.csv
|
|
│
|
|
├── csv/
|
|
│ ├── weather.csv
|
|
│ ├── panel.csv
|
|
│ ├── combiner.csv
|
|
│ ├── inverter.csv
|
|
│ ├── plant.csv
|
|
│ └── faults.csv
|
|
│
|
|
└── parquet/
|
|
├── weather.parquet
|
|
├── panel.parquet
|
|
├── combiner.parquet
|
|
├── inverter.parquet
|
|
├── plant.parquet
|
|
└── faults.parquet
|
|
```
|
|
|
|
---
|
|
|
|
## Data Model
|
|
|
|
Each simulation timestep produces records at every level of the hierarchy.
|
|
|
|
**Panel**
|
|
|
|
| Field | Description |
|
|
|---|---|
|
|
| `timestamp` | Measurement instant |
|
|
| `irradiance_Wm2` | Incident irradiance |
|
|
| `module_temperature_C` | Module temperature |
|
|
| `voltage_V` | Panel voltage |
|
|
| `current_A` | Panel current |
|
|
| `power_W` | Instantaneous power |
|
|
| `energy_Wh` | Energy in timestep |
|
|
| `soiling_factor` | Soiling loss factor |
|
|
| `degradation_factor` | Cumulative degradation |
|
|
| `enabled` | Panel operational status |
|
|
|
|
**Combiner Box**
|
|
|
|
| Field | Description |
|
|
|---|---|
|
|
| `dc_power_W` | Aggregated DC power |
|
|
| `dc_voltage_V` | Bus voltage |
|
|
| `dc_current_A` | Total current |
|
|
| `active_panel_count` | Active panels |
|
|
| `availability` | Fraction of active panels |
|
|
| `status` | `normal` / `idle` / `fault` |
|
|
|
|
**Inverter**
|
|
|
|
| Field | Description |
|
|
|---|---|
|
|
| `dc_power_W` | DC input power |
|
|
| `ac_power_W` | AC output power |
|
|
| `efficiency` | Conversion efficiency |
|
|
| `clipping_loss_W` | Clipping losses |
|
|
| `temperature_C` | Internal temperature |
|
|
| `status` | `normal` / `idle` / `fault` |
|
|
|
|
**Plant**
|
|
|
|
| Field | Description |
|
|
|---|---|
|
|
| `ac_power_W` | Total AC power |
|
|
| `energy_Wh` | Energy in timestep |
|
|
| `performance_ratio` | PR (AC / nominal) |
|
|
| `availability` | Active panel fraction |
|
|
| `fault_active` | Any active fault |
|
|
|
|
---
|
|
|
|
## Simulation Pipeline
|
|
|
|
```
|
|
pv_simulator/config/plant.json
|
|
│
|
|
▼
|
|
PVPlant (built from config)
|
|
│
|
|
▼
|
|
PVSimulator.run()
|
|
│
|
|
▼
|
|
SimulationResult
|
|
│
|
|
├──────────────────┐
|
|
▼ ▼
|
|
statistics.py exporter.py
|
|
│ │
|
|
▼ ├── CSV
|
|
KPI ├── Parquet
|
|
├── JSON
|
|
└── SQLite (optional)
|
|
```
|
|
|
|
---
|
|
|
|
## Planned Improvements
|
|
|
|
- Single-diode model via `pvlib` for accurate I-V curves
|
|
- Partial shading with bypass diode simulation
|
|
- String-level mismatch modelling
|
|
- Hot-spot simulation
|
|
- Sensor drift and intermittent faults
|
|
- Streaming / chunked export for multi-year simulations at 5-minute resolution
|
|
- Diagnostic alarms per component
|
|
- Interactive dashboard (Plotly / Streamlit)
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
MIT License — see `LICENSE` for details.
|
|
|
|
---
|
|
|
|
> Built as part of the ZAK project — a Linux-based measurement and monitoring platform for industrial and renewable energy systems.
|