breos 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- breos/__init__.py +348 -0
- breos/app.py +79 -0
- breos/app_config.py +332 -0
- breos/app_inputs.py +188 -0
- breos/app_results.py +137 -0
- breos/battery.py +1200 -0
- breos/cli.py +428 -0
- breos/constants.py +130 -0
- breos/data/__init__.py +1 -0
- breos/data/configs/__init__.py +1 -0
- breos/data/configs/costs.json +50 -0
- breos/data/configs/electricity.json +189 -0
- breos/data/configs/emissions.json +218 -0
- breos/data/configs/financials.json +7 -0
- breos/data/configs/locations.json +44 -0
- breos/data/rlp/__init__.py +1 -0
- breos/data/rlp/h0SLP_demandlib_1000kwh_15min.csv +35041 -0
- breos/data/rlp/h0SLP_demandlib_1000kwh_hourly.csv +8761 -0
- breos/economics.py +617 -0
- breos/emissions.py +125 -0
- breos/inverter.py +176 -0
- breos/io.py +357 -0
- breos/load_profiles.py +406 -0
- breos/montecarlo.py +368 -0
- breos/numba_kernels.py +760 -0
- breos/optimization.py +847 -0
- breos/plotting.py +3309 -0
- breos/polysun_degradation.py +293 -0
- breos/pv_modules.py +199 -0
- breos/resources.py +21 -0
- breos/runners/__init__.py +5 -0
- breos/runners/app.py +185 -0
- breos/solar.py +774 -0
- breos/utils.py +159 -0
- breos/weather.py +1027 -0
- breos-0.3.0.dist-info/METADATA +407 -0
- breos-0.3.0.dist-info/RECORD +40 -0
- breos-0.3.0.dist-info/WHEEL +4 -0
- breos-0.3.0.dist-info/entry_points.txt +2 -0
- breos-0.3.0.dist-info/licenses/LICENSE +29 -0
breos/__init__.py
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BREOS - Building Renewable Energy Optimization Software
|
|
3
|
+
|
|
4
|
+
Python library for PV and battery energy-system simulation and optimization.
|
|
5
|
+
Supports both hourly ('h') and 15-minute ('15min') time resolutions.
|
|
6
|
+
|
|
7
|
+
Modules:
|
|
8
|
+
--------
|
|
9
|
+
- weather: Weather data fetching and interpolation
|
|
10
|
+
- solar: PV production calculations
|
|
11
|
+
- load_profiles: Load profile management
|
|
12
|
+
- battery: Energy balance and degradation simulation
|
|
13
|
+
- economics: Cost analysis and projections
|
|
14
|
+
- optimization: System sizing and tilt optimization
|
|
15
|
+
- plotting: Visualization utilities
|
|
16
|
+
- emissions: CO2 savings calculations
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
------
|
|
20
|
+
>>> import breos
|
|
21
|
+
>>> app = breos.App({"location": "porto", "n_modules": 10, "annual_consumption_kwh": 4000})
|
|
22
|
+
>>> app.simulate()
|
|
23
|
+
>>> result = app.result()
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
# Version — resolved from the installed package metadata so it always matches
|
|
27
|
+
# the version declared in pyproject.toml (the single source of truth). This is
|
|
28
|
+
# the same mechanism used by breos/cli.py and docs/conf.py, which keeps the
|
|
29
|
+
# literal from drifting out of sync with the distribution version on a release.
|
|
30
|
+
from importlib.metadata import PackageNotFoundError
|
|
31
|
+
from importlib.metadata import version as _version
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
__version__ = _version("breos")
|
|
35
|
+
except PackageNotFoundError: # running from a source tree without an install
|
|
36
|
+
__version__ = "0.0.0+unknown"
|
|
37
|
+
|
|
38
|
+
# Public facade
|
|
39
|
+
from breos.app import App
|
|
40
|
+
|
|
41
|
+
# Battery
|
|
42
|
+
from breos.battery import (
|
|
43
|
+
BatteryConfig,
|
|
44
|
+
apply_indoor_temperature_model,
|
|
45
|
+
compute_cell_temperature,
|
|
46
|
+
compute_halfcycle_energy_throughput,
|
|
47
|
+
detect_cycles_rainflow,
|
|
48
|
+
detect_half_cycles_from_soc_series,
|
|
49
|
+
k_c_rate_Q,
|
|
50
|
+
k_c_rate_R,
|
|
51
|
+
k_doc_Q,
|
|
52
|
+
k_doc_R,
|
|
53
|
+
resistance_to_efficiency,
|
|
54
|
+
simulate_energy_balance,
|
|
55
|
+
update_battery_resistance_calendar,
|
|
56
|
+
update_battery_resistance_cyclewise,
|
|
57
|
+
update_battery_soc,
|
|
58
|
+
update_battery_soh_calendar,
|
|
59
|
+
update_battery_soh_cyclewise,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Constants
|
|
63
|
+
from breos.constants import (
|
|
64
|
+
A_Q,
|
|
65
|
+
A_R,
|
|
66
|
+
B_Q,
|
|
67
|
+
B_R,
|
|
68
|
+
C_DOC_Q,
|
|
69
|
+
C_DOC_R,
|
|
70
|
+
D_DOC_Q,
|
|
71
|
+
D_DOC_R,
|
|
72
|
+
DEFAULT_CHARGE_EFFICIENCY,
|
|
73
|
+
DEFAULT_DISCHARGE_EFFICIENCY,
|
|
74
|
+
DEFAULT_INDOOR_CEILING_C,
|
|
75
|
+
DEFAULT_INDOOR_COUPLING_ALPHA,
|
|
76
|
+
DEFAULT_INDOOR_FLOOR_C,
|
|
77
|
+
DEFAULT_INDOOR_SETPOINT_C,
|
|
78
|
+
DEFAULT_MAX_SOC,
|
|
79
|
+
DEFAULT_MIN_SOC,
|
|
80
|
+
LAM_EA_J_MOL,
|
|
81
|
+
LAM_EXPONENT_B,
|
|
82
|
+
LAM_K0_FRAC,
|
|
83
|
+
LAM_SOC_EXPONENT_N,
|
|
84
|
+
NAUMANN_EA_J_MOL,
|
|
85
|
+
NAUMANN_EA_R_J_MOL,
|
|
86
|
+
NAUMANN_EXPONENT_B,
|
|
87
|
+
NAUMANN_K0_PERCENT,
|
|
88
|
+
NAUMANN_K0_R_PERCENT,
|
|
89
|
+
NAUMANN_SOC_EXPONENT_N,
|
|
90
|
+
R_GAS,
|
|
91
|
+
T_REF_K,
|
|
92
|
+
Z_Q,
|
|
93
|
+
Z_R,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Economics
|
|
97
|
+
from breos.economics import (
|
|
98
|
+
CostParams,
|
|
99
|
+
calculate_costs,
|
|
100
|
+
calculate_lcoe,
|
|
101
|
+
calculate_lcoe_from_projection,
|
|
102
|
+
cost_analysis_projection,
|
|
103
|
+
cost_params_from_config,
|
|
104
|
+
find_payback_year,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Emissions
|
|
108
|
+
from breos.emissions import (
|
|
109
|
+
EmissionsParams,
|
|
110
|
+
calculate_co2_projection,
|
|
111
|
+
calculate_co2_savings,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Inverter
|
|
115
|
+
from breos.inverter import (
|
|
116
|
+
INVERTER_PRESETS,
|
|
117
|
+
InverterConfig,
|
|
118
|
+
InverterConversionResult,
|
|
119
|
+
calculate_dc_ac_power,
|
|
120
|
+
get_inverter_preset,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# I/O (export/import functions)
|
|
124
|
+
from breos.io import (
|
|
125
|
+
export_cost_analysis,
|
|
126
|
+
export_monthly_summary,
|
|
127
|
+
export_results,
|
|
128
|
+
export_summary,
|
|
129
|
+
export_yearly_summary,
|
|
130
|
+
load_results,
|
|
131
|
+
save_simulation_report,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Load Profiles
|
|
135
|
+
from breos.load_profiles import (
|
|
136
|
+
align_load_to_pv,
|
|
137
|
+
load_profile,
|
|
138
|
+
scale_to_annual_consumption,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Monte Carlo (weather + demand uncertainty)
|
|
142
|
+
from breos.montecarlo import (
|
|
143
|
+
MonteCarloResult,
|
|
144
|
+
MonteCarloSettings,
|
|
145
|
+
run_montecarlo,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Optimization
|
|
149
|
+
from breos.optimization import (
|
|
150
|
+
OptimizationResult,
|
|
151
|
+
optimize_battery_size,
|
|
152
|
+
optimize_system_multi_objective,
|
|
153
|
+
optimize_tilt,
|
|
154
|
+
optimize_tilt_brent,
|
|
155
|
+
size_for_zeb,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Polysun Degradation (comparison baseline)
|
|
159
|
+
from breos.polysun_degradation import (
|
|
160
|
+
PolysunDegradationConfig,
|
|
161
|
+
compute_dod_histogram,
|
|
162
|
+
compute_miner_damage,
|
|
163
|
+
predict_polysun_lifetime,
|
|
164
|
+
simulate_polysun_degradation,
|
|
165
|
+
woehler_cycles_to_failure,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# PV Module Database
|
|
169
|
+
from breos.pv_modules import (
|
|
170
|
+
MODULES,
|
|
171
|
+
get_module,
|
|
172
|
+
get_module_info,
|
|
173
|
+
list_modules,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# Solar
|
|
177
|
+
from breos.solar import (
|
|
178
|
+
PVModuleParams,
|
|
179
|
+
calculate_multi_array_production,
|
|
180
|
+
calculate_pv_production_ac,
|
|
181
|
+
calculate_pv_production_dc,
|
|
182
|
+
calculate_pv_production_dc_tracking,
|
|
183
|
+
calculate_pv_production_tmy,
|
|
184
|
+
dc_to_ac,
|
|
185
|
+
default_azimuth,
|
|
186
|
+
estimate_optimal_tilt,
|
|
187
|
+
zeb_sizer,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Utils
|
|
191
|
+
from breos.utils import (
|
|
192
|
+
count_leap_years,
|
|
193
|
+
get_hours_per_step,
|
|
194
|
+
get_steps_per_day,
|
|
195
|
+
get_steps_per_year,
|
|
196
|
+
is_leap_year,
|
|
197
|
+
number_of_cores,
|
|
198
|
+
remap_datetime_index_years,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Weather
|
|
202
|
+
from breos.weather import (
|
|
203
|
+
build_battery_temperature_series,
|
|
204
|
+
csv_15min_to_hourly,
|
|
205
|
+
csv_hourly_to_15min,
|
|
206
|
+
extract_ambient_temperature,
|
|
207
|
+
fetch_tmy_nsrdb,
|
|
208
|
+
fetch_tmy_weather_data,
|
|
209
|
+
fetch_weather_data,
|
|
210
|
+
load_weather,
|
|
211
|
+
parse_weather_filename,
|
|
212
|
+
preload_weather_by_year,
|
|
213
|
+
read_epw_file,
|
|
214
|
+
resample_tmy_to_15min,
|
|
215
|
+
resample_to_15min,
|
|
216
|
+
resample_to_hourly,
|
|
217
|
+
select_random_year_and_replace_datetime,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Plotting (try to import, skip if matplotlib not installed)
|
|
221
|
+
try:
|
|
222
|
+
from breos.plotting import (
|
|
223
|
+
create_cost_plots,
|
|
224
|
+
degradation_plots,
|
|
225
|
+
monthly_graphs,
|
|
226
|
+
plot_azitilt_ew_1d,
|
|
227
|
+
plot_azitilt_landscape_2d,
|
|
228
|
+
plot_azitilt_landscape_3d,
|
|
229
|
+
plot_battery_soh_timeseries,
|
|
230
|
+
plot_breakeven,
|
|
231
|
+
plot_breakeven_comparison,
|
|
232
|
+
plot_breakeven_two,
|
|
233
|
+
# Sensitivity analysis
|
|
234
|
+
plot_calendar_aging_sensitivity,
|
|
235
|
+
plot_cell_temperature,
|
|
236
|
+
# CO2 savings
|
|
237
|
+
plot_co2_savings,
|
|
238
|
+
# Polysun vs BREOS comparison
|
|
239
|
+
plot_degradation_methodology_comparison,
|
|
240
|
+
# Batch comparison
|
|
241
|
+
plot_grid_independence_heatmap,
|
|
242
|
+
plot_lifetime_prediction_comparison,
|
|
243
|
+
plot_location_comparison_delta,
|
|
244
|
+
plot_loo_cv_summary,
|
|
245
|
+
plot_loo_param_stability,
|
|
246
|
+
plot_loo_predictions,
|
|
247
|
+
# Monte Carlo distributions
|
|
248
|
+
plot_montecarlo_final_soh_distribution,
|
|
249
|
+
plot_montecarlo_grid_independence_distribution,
|
|
250
|
+
plot_montecarlo_npv_distribution,
|
|
251
|
+
plot_montecarlo_simulation,
|
|
252
|
+
plot_monthly_balance,
|
|
253
|
+
plot_monthly_comparison,
|
|
254
|
+
plot_pareto_front_analysis,
|
|
255
|
+
plot_resistance_and_efficiency,
|
|
256
|
+
plot_temperature_sensitivity_comparison,
|
|
257
|
+
plot_tilt_optimization,
|
|
258
|
+
plot_timeseries,
|
|
259
|
+
plot_validation_degradation_split,
|
|
260
|
+
plot_validation_multi_system,
|
|
261
|
+
plot_validation_parity,
|
|
262
|
+
plot_validation_residuals,
|
|
263
|
+
plot_validation_soh_comparison,
|
|
264
|
+
plot_weather_annual_ghi_distribution,
|
|
265
|
+
plot_weather_monthly_comparison,
|
|
266
|
+
set_presentation_mode,
|
|
267
|
+
weekly_graphs,
|
|
268
|
+
yearly_graphs,
|
|
269
|
+
)
|
|
270
|
+
except ImportError:
|
|
271
|
+
pass # matplotlib not installed
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
# Numba kernels (lazy import to avoid slow import at package load)
|
|
275
|
+
def _get_numba():
|
|
276
|
+
"""Lazy import of Numba-accelerated kernels."""
|
|
277
|
+
from breos import numba_kernels
|
|
278
|
+
|
|
279
|
+
return numba_kernels
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
__all__ = [
|
|
283
|
+
# Public facade
|
|
284
|
+
"App",
|
|
285
|
+
# Version
|
|
286
|
+
"__version__",
|
|
287
|
+
# Configuration and result objects
|
|
288
|
+
"BatteryConfig",
|
|
289
|
+
"CostParams",
|
|
290
|
+
"EmissionsParams",
|
|
291
|
+
"InverterConfig",
|
|
292
|
+
"InverterConversionResult",
|
|
293
|
+
"OptimizationResult",
|
|
294
|
+
"PVModuleParams",
|
|
295
|
+
# Weather
|
|
296
|
+
"load_weather",
|
|
297
|
+
"fetch_tmy_weather_data",
|
|
298
|
+
"fetch_tmy_nsrdb",
|
|
299
|
+
"fetch_weather_data",
|
|
300
|
+
"read_epw_file",
|
|
301
|
+
# Solar
|
|
302
|
+
"calculate_pv_production_dc",
|
|
303
|
+
"calculate_pv_production_dc_tracking",
|
|
304
|
+
"calculate_multi_array_production",
|
|
305
|
+
"calculate_pv_production_ac",
|
|
306
|
+
"dc_to_ac",
|
|
307
|
+
"estimate_optimal_tilt",
|
|
308
|
+
"default_azimuth",
|
|
309
|
+
# PV module catalogue
|
|
310
|
+
"get_module",
|
|
311
|
+
"get_module_info",
|
|
312
|
+
"list_modules",
|
|
313
|
+
# Load Profiles
|
|
314
|
+
"load_profile",
|
|
315
|
+
"scale_to_annual_consumption",
|
|
316
|
+
"align_load_to_pv",
|
|
317
|
+
# Inverter
|
|
318
|
+
"get_inverter_preset",
|
|
319
|
+
"calculate_dc_ac_power",
|
|
320
|
+
# Battery
|
|
321
|
+
"simulate_energy_balance",
|
|
322
|
+
"apply_indoor_temperature_model",
|
|
323
|
+
# Emissions
|
|
324
|
+
"calculate_co2_savings",
|
|
325
|
+
"calculate_co2_projection",
|
|
326
|
+
# Economics
|
|
327
|
+
"calculate_costs",
|
|
328
|
+
"cost_analysis_projection",
|
|
329
|
+
"cost_params_from_config",
|
|
330
|
+
"find_payback_year",
|
|
331
|
+
"calculate_lcoe",
|
|
332
|
+
"calculate_lcoe_from_projection",
|
|
333
|
+
# Optimization
|
|
334
|
+
"optimize_tilt",
|
|
335
|
+
"optimize_tilt_brent",
|
|
336
|
+
"optimize_battery_size",
|
|
337
|
+
"optimize_system_multi_objective",
|
|
338
|
+
# Monte Carlo
|
|
339
|
+
"run_montecarlo",
|
|
340
|
+
"MonteCarloSettings",
|
|
341
|
+
"MonteCarloResult",
|
|
342
|
+
# I/O
|
|
343
|
+
"export_results",
|
|
344
|
+
"export_summary",
|
|
345
|
+
"load_results",
|
|
346
|
+
"export_monthly_summary",
|
|
347
|
+
"export_yearly_summary",
|
|
348
|
+
]
|
breos/app.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BREOS public facade - single entry point for PV + battery simulations.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
import breos
|
|
6
|
+
|
|
7
|
+
app = breos.App({
|
|
8
|
+
"location": "porto",
|
|
9
|
+
"n_modules": 10,
|
|
10
|
+
"annual_consumption_kwh": 4000,
|
|
11
|
+
"battery_kwh": 5.0,
|
|
12
|
+
"cost_preset": "residential_pt",
|
|
13
|
+
"emissions_country": "PT",
|
|
14
|
+
})
|
|
15
|
+
app.simulate()
|
|
16
|
+
result = app.result()
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
from breos.app_config import resolve_app_config
|
|
24
|
+
from breos.app_inputs import AppRuntimeDependencies
|
|
25
|
+
from breos.app_results import build_result as build_app_result
|
|
26
|
+
from breos.load_profiles import load_profile
|
|
27
|
+
from breos.runners.app import run_app_simulation
|
|
28
|
+
from breos.weather import build_battery_temperature_series, fetch_tmy_weather_data, load_weather, resample_to_15min
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class App:
|
|
32
|
+
"""
|
|
33
|
+
Single entry point for BREOS simulations.
|
|
34
|
+
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
config : dict
|
|
38
|
+
Simulation configuration. Required keys:
|
|
39
|
+
|
|
40
|
+
- ``location`` - preset key (``"porto"``) **or** dict with
|
|
41
|
+
``latitude``, ``longitude``, ``timezone``.
|
|
42
|
+
- ``n_modules`` - number of PV modules (int, > 0), unless
|
|
43
|
+
``pv_arrays`` is provided.
|
|
44
|
+
- ``annual_consumption_kwh`` - yearly electricity demand (float, > 0).
|
|
45
|
+
|
|
46
|
+
Optional keys include battery size, PV arrays, module selection, load
|
|
47
|
+
profile, tracking, resolution, projection years, cost and emissions
|
|
48
|
+
presets, degradation, and inverter assumptions.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, config: dict) -> None:
|
|
52
|
+
self._resolved = resolve_app_config(config)
|
|
53
|
+
self._cfg = self._resolved.cfg
|
|
54
|
+
self._result: dict[str, Any] | None = None
|
|
55
|
+
|
|
56
|
+
def simulate(self) -> None:
|
|
57
|
+
"""Run the full simulation pipeline."""
|
|
58
|
+
artifacts = run_app_simulation(self._cfg, self._resolved, self._runtime_dependencies())
|
|
59
|
+
self._result = build_app_result(self._cfg, self._resolved, artifacts)
|
|
60
|
+
|
|
61
|
+
def result(self) -> dict[str, Any]:
|
|
62
|
+
"""
|
|
63
|
+
Return simulation results as a plain dict.
|
|
64
|
+
|
|
65
|
+
Raises ``RuntimeError`` if :meth:`simulate` has not been called.
|
|
66
|
+
"""
|
|
67
|
+
if self._result is None:
|
|
68
|
+
raise RuntimeError("Call simulate() before result().")
|
|
69
|
+
return self._result
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def _runtime_dependencies() -> AppRuntimeDependencies:
|
|
73
|
+
return AppRuntimeDependencies(
|
|
74
|
+
load_profile=load_profile,
|
|
75
|
+
load_weather=load_weather,
|
|
76
|
+
fetch_tmy_weather_data=fetch_tmy_weather_data,
|
|
77
|
+
resample_to_15min=resample_to_15min,
|
|
78
|
+
build_battery_temperature_series=build_battery_temperature_series,
|
|
79
|
+
)
|