Skip to main content

Python library for PV and battery energy-system simulation and optimization

Project description

BREOS - Building Renewable Energy Optimization Software

Tests PyPI License: BSD-3 Python 3.11+

A Python library for PV and battery energy-system simulation and optimization, designed for research and engineering applications.

Features

  • Weather data: Fetch TMY data from PVGIS/NSRDB and historical data from Open-Meteo. Support for hourly and 15-minute resolutions with Makima interpolation.
  • PV production: DC and AC power calculations using pvlib, with built-in module database and inverter presets.
  • Battery simulation: Energy balance with calendar and cycle aging models (Naumann 2020, Lam 2025) and field-calibrated LFP parameters. Optional approximate Numba kernels for fast standalone screening studies.
  • Economics: NPV, LCOE, breakeven analysis, and cost projections with configurable tariffs and inflation.
  • Optimization: Multi-objective (grid independence, NPV, ZEB ratio) system sizing using pymoo (NSGA-II). Tilt/azimuth optimization via grid search or Brent's method.
  • Emissions: CO2 savings calculations and projections.
  • Visualization: Publication-ready plots for energy balances, degradation, breakeven, Pareto fronts, and more.
  • Load profiles: Bundled demandlib-derived H0 examples, plus support for user-supplied BDEW, E-REDES, REE, and custom profiles.

Installation

pip install breos

Or with uv:

uv add breos          # as a project dependency
uvx breos --version   # run the CLI without installing

Optional feature groups keep the default install focused on core PV + battery simulation:

pip install "breos[plots]"          # publication plots
pip install "breos[optimization]"   # pymoo multi-objective sizing
pip install "breos[weather]"        # Open-Meteo historical weather fetching
pip install "breos[fast]"           # approximate Numba screening kernels (not used by App)
pip install "breos[validation]"     # Excel / Arrow validation workflows

To install from source instead:

git clone https://github.com/Str4vinci/breos.git
cd breos
pip install -e .

Quick Start

import breos

app = breos.App({
    "location": "porto",              # preset or {"latitude": ..., "longitude": ..., "timezone": ...}
    "n_modules": 10,
    "annual_consumption_kwh": 4000,
    "battery_kwh": 5.0,               # 0 for no battery
    "cost_preset": "residential_pt",
    "emissions_country": "PT",
})

app.simulate()
result = app.result()

print(f"Grid independence: {result['grid_independence_pct']:.1f}%")
print(f"Payback: {result['payback_year']} years")
print(f"NPV savings: {result['npv_savings_eur']:,.0f} EUR")
print(f"CO2 avoided: {result['co2_avoided_total_kg']:,.0f} kg")

result() returns a plain Python dict (JSON-serializable, no pandas). See Configuration for all options.

For real studies, bring your own weather/API access where required, licensed load profiles, PV module/system data, and cost/tariff assumptions. The packaged defaults are intended to make the tool runnable, not to certify a project.

Command Line

Run a simulation without writing Python:

breos run \
  --location porto \
  --n-modules 10 \
  --annual-consumption-kwh 4000 \
  --battery-kwh 5.0 \
  --cost-preset residential-pt \
  --emissions-country pt \
  --output result.json

The CLI writes the same JSON-serializable result returned by App.result(). You can also pass a TOML or JSON config file:

breos run --config configs/examples/quickstart.toml --output result.json

Inspect a config before running the full simulation:

breos validate-config configs/examples/quickstart.toml
breos run --config configs/examples/quickstart.toml --dry-run

Discover packaged option keys:

breos list locations
breos list modules
breos list cost-presets
breos list emissions
breos list load-profiles

For non-bundled RLPs, put licensed CSVs in a local directory and pass it through config or flags:

breos run --config configs/examples/external-rlp.toml --rlp-directory external_rlp

Configuration

All keys except location, annual_consumption_kwh, and either n_modules or pv_arrays are optional with sensible defaults.

Key Default Description
location required Preset key ("porto", "berlin", ...) or dict with latitude, longitude, timezone
n_modules required unless pv_arrays is set Number of PV modules
pv_arrays None Optional list of arrays with modules, module, tilt, and azimuth; when present, the array module total overrides n_modules
annual_consumption_kwh required Annual electricity demand (kWh)
battery_kwh 0.0 Battery capacity (0 = no battery)
pv_module None Module name from catalogue (None = default)
load_profile "1" Bundled demandlib-derived H0 profile. Other standard profiles require caller-supplied CSVs
rlp_directory None Directory containing licensed external RLP CSVs for non-bundled load profiles
tilt auto Tilt angle in degrees (auto-estimated from latitude)
azimuth auto Surface azimuth (auto: 180 for northern hemisphere)
tracking "fixed" Tracking mode ("fixed", "single_axis", or "dual_axis")
axis_tilt 0.0 Single-axis tracker axis tilt
axis_azimuth auto Tracker axis azimuth (auto from latitude)
max_angle 60.0 Single-axis tracker maximum rotation angle
backtrack True Whether single-axis trackers backtrack to avoid row shading
gcr 0.35 Ground coverage ratio for single-axis tracking
cross_axis_tilt 0.0 Cross-axis terrain slope for single-axis tracking
dual_axis_max_tilt 90.0 Maximum panel tilt for dual-axis tracking
resolution "h" Time resolution ("h" or "15min")
projection_years 20 Economic projection horizon
cost_preset None Cost preset key from packaged defaults; editable examples live in configs/base/
inflation_rate 0.02 Annual electricity price inflation
discount_rate 0.03 Discount rate for NPV calculations
emissions_country None Country code for CO2 calculations ("PT", "DE", "ES", ...)
pv_degradation_rate 0.005 Annual PV degradation (0.5%)
calendar_model "naumann_lam_field_calibrated" Battery calendar aging model
battery_min_soc 0.10 Battery SOC floor (fraction of usable capacity)
battery_max_soc 0.90 Battery SOC ceiling
battery_eol_percentage 0.70 SOH fraction that triggers battery replacement
battery_rte None Battery round-trip efficiency, split evenly across charge/discharge (None = 0.95)
dc_coupled True DC-coupled / hybrid inverter
inverter_efficiency 0.96 Inverter efficiency
inverter_loading_ratio 1.25 DC/AC oversizing ratio; also sets the inverter AC rating that clips production
pv_loss_overrides None Per-component overrides (percent) for the fixed PVWatts system losses, e.g. {"shading": 0.0}
start_date "2023-01-01" First simulation date

Modeling conventions

  • System losses: every DC production calculation applies pvlib's PVWatts losses with BREOS defaults of soiling 2%, shading 3%, mismatch 2%, wiring 2%, connections 0.5%, LID 1.5%, nameplate 1%, and availability 3% — about 14.1% combined (breos.solar.DEFAULT_PVWATTS_LOSSES). Age-based degradation is added separately per simulation year. Override individual components with pv_loss_overrides (App) or loss_overrides (solar functions).
  • Inverter: the energy balance applies a flat inverter_efficiency and clips AC output (PV and battery discharge combined) at the inverter rating implied by inverter_loading_ratio — the same rating used for inverter CAPEX. DC surplus above the rating can still charge a DC-coupled battery.

Result

app.result() returns a dict with:

Key Description
pv_production_kwh Year 1 PV production
grid_independence_pct Year 1 grid independence (%)
self_consumption_pct Year 1 self-consumption ratio (%)
total_investment_eur Total CAPEX
payback_year Payback year (None if not reached)
npv_savings_eur NPV savings over projection period
lcoe_eur_kwh Levelized cost of electricity
co2_avoided_year1_kg Year 1 CO2 avoided
co2_avoided_total_kg Lifetime CO2 avoided
battery_soh_end_pct Battery state of health at end (if battery)
monthly Year 1 monthly balance rows for PV, load, imports, exports, and self-consumption
financial Yearly financial projection rows, including year 0 investment
yearly List of per-year dicts with detailed breakdown

Multi-array PV systems

Use pv_arrays when a roof has panels on different faces or orientations:

app = breos.App({
    "location": "porto",
    "annual_consumption_kwh": 4000,
    "pv_arrays": [
        {"modules": 8, "module": "Erlangen_445W", "tilt": 10, "azimuth": 90},
        {"modules": 8, "module": "Erlangen_445W", "tilt": 10, "azimuth": 270},
    ],
})
app.simulate()

BREOS calculates production per array and combines the DC output before the energy balance, so east-west and pitched-roof layouts are not collapsed into a single representative tilt/azimuth.

Advanced Usage

For full control over individual simulation steps, use the lower-level modules directly:

from breos.weather import fetch_tmy_weather_data
from breos.solar import calculate_pv_production_dc, PVModuleParams
from breos.battery import simulate_energy_balance, BatteryConfig
from breos.load_profiles import load_profile
from breos.economics import calculate_costs, cost_analysis_projection
from pvlib.location import Location

# Each module can be used independently
weather, metadata = fetch_tmy_weather_data(41.15, -8.63)
location = Location(41.15, -8.63, tz='Europe/Lisbon')
pv_dc = calculate_pv_production_dc(weather, location, tilt=35, surface_azimuth=180, n_modules=10)
# ...

Additional Capabilities

BREOS is the open-source core of a broader simulation platform developed as part of PhD research. Additional features not included in this release:

  • Time-of-Use (TOU) tariff optimization with multi-period pricing and strategy comparison
  • Vehicle-to-Home (V2H) simulation with EV scheduling and bidirectional charging
  • Multi-chemistry battery support — Sodium-ion (SIB), Vanadium Redox Flow (VRFB), Solid-State (SSB)
  • Thermal energy storage (TES) with phase-change material modeling
  • Heat pump integration with COP modeling and coupled electro-thermal energy balance
  • Community Self-Consumption (CSC) modeling for multi-building scenarios

These modules may be released in the future or are available for academic collaboration upon request.

Weather Data Note

BREOS uses Open-Meteo for historical weather data. Open-Meteo is free for non-commercial use. For commercial applications, please review their pricing and terms.

Two working-directory conventions to be aware of:

  • A weather/ directory in the current working directory is scanned before any PVGIS fetch — a file matching the location preset name is used silently instead of fetching. Remove or rename it to force a fresh fetch.
  • Historical Open-Meteo fetches cache responses in a .cache.sqlite file in the current working directory (30-day expiry).

Library modules report progress (file discovery, saved files, conversions) through the standard logging module under the breos.* logger names — enable them with logging.basicConfig(level=logging.INFO) or silence them per module. Functions with a verbose flag still print to stdout when asked.

Load Profile Data Note

The public package bundles only demandlib-derived H0 example profiles. E-REDES, REE, and direct BDEW CSVs are supported as user-provided files through rlp_directory, but are not redistributed in this repository because their public source terms do not clearly grant package redistribution rights. See ATTRIBUTIONS.md and docs/legal/load-profile-data.md.

Resources

See docs/resources.md for links to PV modelling references, RLP sources, weather/solar-resource APIs, and input assumptions to record.

Citation

If you use BREOS in your research, please cite:

@software{breos,
  author = {Rodrigues, Leonardo},
  title = {BREOS: Building Renewable Energy Optimization Software},
  year = {2026},
  url = {https://github.com/Str4vinci/breos}
}

Roadmap

See ROADMAP.md for planned architectural work and capability extensions.

Contributing

See CONTRIBUTING.md for guidelines.

BREOS uses develop as the default development branch. Feature work should be done on separate branches and opened as pull requests into develop.

The main branch tracks stable releases only. Use main or the GitHub Releases page when you want the latest stable version.

Contact

For questions, collaboration, or access to additional modules, reach out at lrodrigues@fe.up.pt.

License

BSD 3-Clause License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

breos-0.3.0rc1.tar.gz (854.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

breos-0.3.0rc1-py3-none-any.whl (644.7 kB view details)

Uploaded Python 3

File details

Details for the file breos-0.3.0rc1.tar.gz.

File metadata

  • Download URL: breos-0.3.0rc1.tar.gz
  • Upload date:
  • Size: 854.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for breos-0.3.0rc1.tar.gz
Algorithm Hash digest
SHA256 9e9af218532cb9acbdedca78fa0f62b497baac579686335487ebf74296698e27
MD5 c0b1b7a3838a0f4c9445a31c6cad5b4b
BLAKE2b-256 fe080ad3b988c86d46c0d5cded4466576a3a64bbfdfe7a39b78fa44f08dfc93f

See more details on using hashes here.

File details

Details for the file breos-0.3.0rc1-py3-none-any.whl.

File metadata

  • Download URL: breos-0.3.0rc1-py3-none-any.whl
  • Upload date:
  • Size: 644.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for breos-0.3.0rc1-py3-none-any.whl
Algorithm Hash digest
SHA256 76e05a55dc35030fcc8983cfded729e3448502df34d7581aa63086511b30a836
MD5 3a6f54a43e783a2444c9d428aaf1e363
BLAKE2b-256 5e4cfb28db42a5ce60daf206923a92729eea6711e2613f48d8e3b7fa1260a9ce

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page