AI-Powered Solar Simulation β Physics meets Intelligence
| Main Dashboard | Configuration Sidebar |
|---|---|
![]() |
![]() |
| Feature | Description |
|---|---|
| Multi-Agent Architecture | 7 specialized AI agents collaborating on PV system design |
| Hybrid AI + Physics | LLM reasoning + PVlib IEEE-standard calculations |
| Cloud LLM Support | Local Ollama OR cloud providers (OpenRouter, OpenAI) |
| Dynamic Module Database | Auto-fetches 154+ production modules from CEC database |
| Real Weather Data | Open-Meteo archive integration with disk cache and offline synthetic fallback |
| Consolidated Simulation Engine | Single src/simulation.py using pvlib SAPM cell-temperature, ASHRAE IAM, and Hay-Davies transposition |
| Auditable Loss Model | Documented LossModel dataclass (soiling, mismatch, wiring, LID, nameplate, age) with a PVWatts-equivalent realistic() preset |
| Battery + PLN Net Metering | Self-consumption optimizer with PLN tariff calculator |
| Professional PDF Reports | 8-page PDF with charts: monthly production, storage flows, SoC, bill comparison |
| Hemisphere-Aware | Automatic azimuth/tilt for southern hemisphere (0Β° North-facing) |
| Continuous Validation | 36-test suite with PVWatts reference yields for 4 global sites + GitHub Actions CI |
| Validated Results | Performance Ratio matches PVsyst (72.9% vs 72.8%) |
| Global Locations | Pre-configured presets + custom coordinates |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Sunnyside AI Platform β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
β β Geolocation β β Weather β β System Design β β
β β Agent β β Agent β β Agent β β
β ββββββββ¬βββββββ ββββββββ¬βββββββ ββββββββββββ¬βββββββββββββββ β
β β β β β
β ββββββββββββββββββΌβββββββββββββββββββββ β
β βΌ β
β ββββββββββββββββββββββββ β
β β Calculation Engine β β
β β (PVlib Physics) β β
β ββββββββββββ¬ββββββββββββ β
β β β
β ββββββββββββββββββΌβββββββββββββββββ β
β βΌ βΌ βΌ β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Financial β β Report β β Coordinator β β
β β Agent β β Agent β β Agent β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β β
β ββββββββββββ΄βββββββββββ β
β β Battery Agent + β β
β β Storage Optimizer β β
β ββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Python 3.12+
uv(recommended) orpip- Ollama (optional, for local AI features)
# Clone the repository
git clone https://github.com/zakusworo/pv-multi-agent.git
cd pv-multi-agent
# Install dependencies with uv (recommended)
uv sync
# OR install with pip
pip install -e ".[dev]"# Launch the web interface
.venv/bin/streamlit run gui.py --server.port 8501
# Open http://localhost:8501 in your browserWhat you can do:
- Select location (Bandung, Jakarta, Phoenix, Berlin, Bikaner, or custom)
- Pick PV module from live CEC database (154+ modules, 14+ manufacturers)
- Set system capacity, tilt, azimuth
- Choose weather source β real data from Open-Meteo (free, cached locally) or synthetic TMY for offline use
- Enable Battery & PLN Net Metering β calculate self-consumption ratio, bill savings, payback
- Generate AI Insights β get LLM-powered recommendations
- Download PDF Report β professional 5-8 page report with charts
# Start Ollama
ollama serve
# Pull a lightweight model
ollama pull llama3.2:1b
# Run multi-agent simulation
.venv/bin/python3 -m src.pv_agentsexport OPENROUTER_API_KEY=your_key_here
.venv/bin/python3 -m src.pv_agents_cloud --provider openrouter --model qwen3.6:latestpv-multi-agent/
βββ gui.py # Streamlit web interface (entry point)
βββ pyproject.toml # UV/pip dependencies & project config
βββ README.md # This file
βββ CITATION.cff # Citation metadata
βββ LICENSE # MIT License
β
βββ src/ # Core source code
β βββ simulation.py # Canonical PV simulation engine + LossModel
β βββ weather_provider.py # Open-Meteo real-weather provider with cache
β βββ pv_agents.py # Multi-agent system (Ollama)
β βββ pv_agents_cloud.py # Multi-agent system (cloud LLMs)
β βββ storage_engine.py # Battery simulator (SoH, thermal)
β βββ storage_optimizer.py # Self-consumption optimizer
β βββ load_profiles.py # Residential/commercial load profiles
β βββ pln_tariffs.py # PLN tariff database + bill calculator
β βββ pdf_generator.py # Professional PDF report generator
β βββ module_fetcher.py # Dynamic PV module fetcher (CEC)
β βββ ...
β
βββ data/
β βββ pv_module_database.py # Static fallback module database
β βββ weather_cache/ # On-disk Open-Meteo cache (gitignored)
β
βββ docs/
β βββ screenshots/ # GUI screenshots
β βββ DEPLOYMENT.md # Deployment guide
β βββ VALIDATION_REPORT.md # PVsyst comparison study
β βββ ...
β
βββ scripts/
β βββ check_ollama.py # Ollama setup verification
β
βββ reports/ # Generated text reports
βββ tests/
β βββ test_core.py # Core simulation, battery, tariff tests
β βββ test_validation.py # PVWatts reference-yield regression tests
β βββ test_weather_provider.py # Open-Meteo provider (mocked HTTP)
β βββ data/
β βββ validation_references.json
βββ .github/
βββ workflows/
βββ test.yml # GitHub Actions CI (pytest on push/PR)
| Location | Lat, Lon | Hemisphere | Auto Azimuth |
|---|---|---|---|
| Bandung, Indonesia | -6.9147, 107.6098 | Southern | 0Β° (North) |
| Jakarta, Indonesia | -6.2088, 106.8456 | Southern | 0Β° (North) |
| Phoenix, USA | 33.4484, -112.0740 | Northern | 180Β° (South) |
| Berlin, Germany | 52.5200, 13.4050 | Northern | 180Β° (South) |
| Bikaner, India | 28.06, 73.30 | Northern | 180Β° (South) |
The professional PDF report includes:
- Cover Page β Project name, coordinates, key metrics (production, yield, PR, cost, payback, LCOE)
- Location & System β Site info, solar geometry, system design details
- Energy Production β Monthly bar chart + detailed monthly data table
- Financial Analysis β Investment summary, performance metrics, disclaimer
- Hourly Output β First-week sample chart showing daily generation pattern
- Storage Analysis (optional) β When battery is enabled:
- System metrics (self-consumption ratio, self-sufficiency, savings)
- Energy flow annual summary
- Stacked area chart: typical week flows
- Battery SoC chart with target lines
- PLN bill comparison with savings annotation
- Monthly energy flows grouped bar chart
- Battery agent recommendation
from simulation import simulate_pv_system, LossModel
# Plane-of-array irradiance β Hay-Davies sky-diffuse transposition
poa = irradiance.get_total_irradiance(
tilt, azimuth, solar_pos['zenith'], solar_pos['azimuth'],
dni, ghi, dhi, model='haydavies',
)
# Optical loss β ASHRAE incidence-angle modifier on the beam component
poa_eff = poa['poa_direct'] * iam.ashrae(aoi) + poa['poa_diffuse']
# Cell temperature β pvlib SAPM open-rack glass-glass
t_cell = temperature.sapm_cell(poa_eff, temp_air, wind_speed,
**TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass'])
# DC + system losses + inverter β single PVWatts-style equation
dc = dc_capacity * (poa_eff / 1000) * (1 + gamma * (t_cell - 25)) * losses.total_derate()
ac = (dc * eta_inv).clip(upper=ac_capacity)from simulation import LossModel
# Default β zero losses (physics-only baseline)
losses = LossModel()
# Or PVWatts-equivalent ~14% stack
losses = LossModel.realistic()
# soiling 2% + mismatch 2% + wiring 2% + connections 0.5%
# + LID 1.5% + nameplate 1% = 9% (plus inverter 4% = ~13% net)
# Pass to the simulation
specs = {..., "losses": losses}
results = simulate_pv_system(specs, weather)from src.pv_agents_cloud import LLMProvider
# Local Ollama
llm = LLMProvider(provider="ollama", model="llama3.2:1b")
# Cloud via OpenRouter
llm = LLMProvider(
provider="openrouter",
model="qwen3.6:latest",
api_key="sk-..."
)
response = llm.chat(messages, temperature=0.3)Reference comparison (PVsyst):
| Metric | PVsyst (Reference) | Sunnyside AI | Difference |
|---|---|---|---|
| Performance Ratio | 72.8% | 72.9% | +0.1% |
| GHI | 1911 kWh/mΒ² | 1848 kWh/mΒ² | β3.3% |
Performance Ratio validated against PVsyst within 0.1 percentage point. See docs/VALIDATION_REPORT.md for full methodology.
Continuous regression suite (tests/test_validation.py):
parametrised yield/PR/capacity-factor checks against NREL PVWatts reference values for 4 sites (Bandung, Yogyakarta, Surabaya, Phoenix). 35 passing, 1 documented xfail (Phoenix yield with synthetic TMY β covered by real weather in production). Runs on every push via GitHub Actions.
.venv/bin/streamlit run gui.py- Push to GitHub (
git push origin master) - Go to https://share.streamlit.io
- Connect
zakusworo/pv-multi-agent, branchmaster, main filegui.py - Add secrets:
OPENROUTER_API_KEY=... - Deploy β live in ~2 minutes
FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install -e .
EXPOSE 8501
CMD ["streamlit", "run", "gui.py", "--server.address=0.0.0.0"]See docs/DEPLOYMENT.md for Hugging Face Spaces, Railway, and other options.
Areas open for contribution:
- Seasonal tilt optimizer (variable tilt throughout the year)
- Additional weather backends (NSRDB, Solargis) alongside the existing Open-Meteo provider
- Shading analysis (LiDAR / 3D horizon import)
- Real-time monitoring dashboard
- Multi-language support (Bahasa Indonesia, Deutsch, Hindi)
- Commercial/industrial load profile refinements for Indonesia
@software{sunnyside_ai_2026,
author = {Kusworo, Zulfikar Aji},
title = {Sunnyside AI: Multi-Agent PV Solar Simulation Platform},
year = {2026},
url = {https://github.com/zakusworo/pv-multi-agent},
version = {1.1.0},
publisher = {GitHub},
doi = {10.5281/zenodo.19650332}
}MIT License β Open for research and commercial use. Attribution required for academic publications.
Built with: Python Β· PVlib Β· Streamlit Β· Ollama Β· OpenRouter Β· fpdf2 Β· Multi-Agent Architecture
Author: Zulfikar Aji Kusworo Contact: greataji13@gmail.com

