# ☀️ 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 `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 ``` 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.