Recipes#
Copy-paste starting points for common setups. Save any block below as
config.toml, then:
breos validate-config config.toml # check resolved choices first
breos run --config config.toml --output result.json
Every key works identically as a Python dict passed to
App. Valid option keys for locations, modules, cost
presets, emissions countries, and load profiles are listed on the
packaged options page or via breos list.
PV-only home#
Set battery_kwh = 0 to disable storage. Investment, payback, and NPV then
reflect the PV system alone, and battery-specific result keys are omitted:
location = "porto"
n_modules = 10
annual_consumption_kwh = 4000
battery_kwh = 0.0
cost_preset = "residential_pt"
emissions_country = "PT"
PV plus battery#
The packaged quickstart, configs/examples/quickstart.toml:
location = "porto"
n_modules = 10
annual_consumption_kwh = 4000
battery_kwh = 5.0
load_profile = "demandlib_h0"
cost_preset = "residential_pt"
emissions_country = "PT"
projection_years = 20
resolution = "h"
See the quickstart for representative output values.
Custom latitude / longitude / timezone#
Any site works without a packaged preset — pass coordinates and an IANA timezone instead of a location key:
location = { latitude = 48.2082, longitude = 16.3738, timezone = "Europe/Vienna" }
n_modules = 12
annual_consumption_kwh = 4500
battery_kwh = 5.0
cost_preset = "residential_de"
emissions_country = "AT"
Tilt and azimuth are auto-estimated from the latitude when not set. There is no Austrian cost preset yet, so this example borrows the German one — replace it with your own tariffs for real economics.
East-west roof with pv_arrays#
Each array is simulated independently and the DC output is combined before
the energy balance, so an east-west layout is not collapsed into one
representative orientation. n_modules is derived from the array totals:
location = "porto"
annual_consumption_kwh = 4000
battery_kwh = 5.0
cost_preset = "residential_pt"
emissions_country = "PT"
[[pv_arrays]]
modules = 8
module = "Erlangen_445W"
tilt = 10
azimuth = 90 # east
[[pv_arrays]]
modules = 8
module = "Erlangen_445W"
tilt = 10
azimuth = 270 # west
Anisotropic sky-diffusion model#
The default isotropic transposition underestimates plane-of-array
irradiance on clear days. Switch to an anisotropic model — here Perez — to
capture circumsolar and horizon brightening. No extra weather inputs are
needed; see Sky-diffusion model:
location = "porto"
n_modules = 10
annual_consumption_kwh = 4000
cost_preset = "residential_pt"
emissions_country = "PT"
transposition_model = "perez"
surface_type = "grass" # or a numeric albedo, e.g. albedo = 0.2
surface_type (or a numeric albedo) sets the ground reflectance that feeds
the ground-diffuse component; a snowy or sandy foreground ("snow", "sand")
raises annual yield further. Leave both unset to keep pvlib’s 0.25 default.
From the CLI, the equivalent flag is --transposition-model perez
(alias --sky-model).
Parameter sweep#
Use breos sweep when you want to run the same scenario over an explicit grid
of App config values. The top-level keys define the base scenario; every key
under [sweep] replaces the matching top-level key for each run. The command
runs the Cartesian product and writes one CSV row per combination:
location = "porto"
n_modules = 10
annual_consumption_kwh = 4000
battery_kwh = 0.0
load_profile = "demandlib_h0"
cost_preset = "residential_pt"
emissions_country = "PT"
projection_years = 20
resolution = "h"
[sweep]
n_modules = [8, 10, 12]
battery_kwh = [0.0, 5.0]
breos sweep --config config.toml --output sweep_results.csv
The output includes the varied parameters (param_* columns), resolved system
sizing, the BREOS version, and top-level scalar result metrics such as grid
independence, NPV, payback, LCOE, and battery replacement totals. This is
explicit enumeration, not an optimizer; use the optimization API for searching
over objectives and constraints.
15-minute resolution#
Hourly weather is interpolated to 15-minute steps (Makima), and the bundled H0 profile has a native 15-minute variant. Simulations take correspondingly longer:
location = "porto"
n_modules = 10
annual_consumption_kwh = 4000
battery_kwh = 5.0
resolution = "15min"
cost_preset = "residential_pt"
emissions_country = "PT"
External load profile (E-REDES, BDEW, REE)#
Only the demandlib-derived H0 profile ("1", alias "demandlib_h0") ships
with BREOS. For the other standard profiles, download the source CSVs yourself
under terms that permit your use, put them in a local directory, and point
rlp_directory at it.
Load Profile Data lists the exact expected
filenames per profile key:
rlp_directory = "external_rlp"
location = "porto"
n_modules = 10
annual_consumption_kwh = 4000
battery_kwh = 5.0
load_profile = "6" # E-REDES BTN C
resolution = "15min"
cost_preset = "residential_pt"
emissions_country = "PT"
A runnable template also ships in the repository as
configs/examples/external-rlp.toml.
Offline runs with cached weather#
When the config uses a location preset key, BREOS scans a weather/
directory in the current working directory before fetching from PVGIS, and
silently reuses a file named <location>_tmy_<year0>_<year1>_<source>.csv.
Seed the cache once while online:
from pathlib import Path
from breos.weather import fetch_tmy_weather_data
Path("weather").mkdir(exist_ok=True)
tmy, _ = fetch_tmy_weather_data(
latitude=41.1579,
longitude=-8.6291,
timezone="Europe/Lisbon",
)
tmy.to_csv("weather/porto_tmy_2005_2023_pvgis-sarah3.csv")
Subsequent runs from the same working directory work without network access
(the log line Found local weather file confirms the cache hit). Custom
coordinate-dict locations always fetch; delete or rename the file to force a
fresh fetch. The filename’s year and source parts only need to match the
pattern — they are metadata, not lookup keys.