Getting started#
REHO is available as a PyPI package and can be installed via pip with:
Full code can be accessed from the REHO repository and project cloned using the command:
Prerequisites#
Python 3#
You will need Python3. REHO is compatible with Python 3.9 and above.
As IDE we recommend to use PyCharm, but Visual Studio Code (VS Code) is also a good choice.
AMPL#
AMPL syntax#
For most convenient use, we recommend using a text editor that supports AMPL syntax highlighting. As PyCharm does not currently provide an extension for AMPL syntax, we suggest using a different editor for AMPL files such as Sublime Text, with its AMPL Highlighting package. VS Code in turn features several extensions for AMPL.
For a quick introduction to AMPL syntax, please refer to AMPL Resoures - Quick introduction.
AMPL license#
As REHO is based on AMPL, it requires an AMPL licence. There are two main options:
You already have an AMPL licence (standard or custom licence for research, teaching, business, consultant) and you know the path to your licence file.
You plan to use the free AMPL Community Edition. This AMPL license is full-sized and full-featured for personal, academic, and commercial-prototyping use. Since 2023, there are no more restrictions on the number of variables or constraints one can use. This Community Edition operates on a cloud license, requiring an internet connection to function.
Note
You do not strictly need to install AMPL on your machine, as AMPL modules will be automatically installed in your environment with REHO. However, you will need to either activate your cloud license or provide your local license path. Come back to this section after you have installed REHO, either from PyPI or from source, to set up your license accordingly.
Additional information and support can be found in the amplpy
library documentation (AMPL Python API).
Warning
Running code from VS Code or Terminal
Running scripts from VS Code or from a standalone terminal may lead to path issues, either when importing the REHO module or when providing the path to .env
.
Please refer to the issue raised in REHO/Issues/Relative Path in VS Code.
Solver#
REHO requires at least one linear programming solver.
The requirements already specify the installation of the HiGHS solver, which is chosen by default when performing an optimization.
However, you have the possibility to install other open-source or licensed solvers, and specify them in the REHO(solver="...")
class constructor. The Gurobi solver works particularly well with REHO, with a calculation time reduced by a factor of 3 compared to HiGHS.
Please refer to AMPL Modules for Python page further insights about AMPL solvers available.
PostgreSQL#
For large-scale applications, REHO can be connected to relational database management systems. The QBuildings database used as a reference for the input to REHO is built with PostgreSQL.
More specifically, the psycopg2 library is used to connect to the database and execute queries in Python. This library is already included in the REHO requirements but is known to cause some issues, as some prerequisites are frequently missing (i.e. the PostgreSQL package and Python development tools).
Note
For Windows users, the binary wheel psycopg2-binary
is already specified in REHO requirements so this should no longer be an issue.
For Linux and Mac users, 2 options are suggested:
psycopg2-binary
insteadpip install psycopg2-binary
psycopg2
from sourcesudo apt install python3-dev libpq-dev
brew install postgresql
You may refer to the discussion How to install psycopg2 with âpipâ on Python? for additional support.
Installation#
From PyPI#
Command#
Select the project root containing a Python environment and install the latest stable release of REHO with:
pip install --extra-index-url https://pypi.ampl.com REHO
Checking proper installation#
Entry points allow to verify the proper installation of REHO:
reho-test-import
reho-test-run
If your installation is correct, you should:
See the results of the optimizations in the terminal.
See files appear in the newly created subfolders
data/clustering/
andresults/
andfigures/
.Have an overview of a Sankey diagram in your web browser.
reho-download-examples
This command will download files from the scripts/examples/
folder from the repository, and copy them locally in the working directory.
Finally, the folder reho/test/
contains several scripts written with pytest, allowing to check for REHO functionalities.
From source#
Command#
Select your project directory and clone the REHO repository with:
git clone https://github.com/IPESE/REHO.git
Warning
The REHO repository can be forked or cloned depending on the intended use. If you simply clone the repository do not forget to check out your own branch from the main
.
Requirements#
Please include a venv
at the project root folder and install dependencies with:
pip install -r requirements.txt
Checking proper installation#
Run any of the files in reho/test/
or scripts/examples/
folders.
If your installation is correct, each run should end with âProcess finished with exit code 0â. Some scripts will also render some results in your web browser and open different tabs showing the outcome of your optimization.
Warning
In scripts/examples/
, the solver is always explicitly set to Gurobi to reduce calculation time. But you can simply remove the REHO(solver="gurobi")
argument and the open-source solver HiGHS will be used by default instead.
Git tracking#
You will also see some files appear in some newly created subfolders such as data/clustering/
, results/
and figures/
. These are not git-tracked. But all the other Python files in scripts/examples/
are git-tracked.
You should then be careful to not modify the content of these files.
However, for your future work and own case-studies with REHO, you can create any additional subfolders in scripts/
. These will be ignored by the git versioning.
Running REHO#
The following paragraphs describe the content of reho/test/test_run.py
and reho/test/test_plot.py
. These latter should allow you to get started with the tool and conduct your first optimizations.
import pytest
from reho.model.reho import *
from reho.plotting import plotting
def test_run(save_results=True):
try:
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=71, egid=['1009515'])
# Select clustering options for weather data
cluster = {'Location': 'Geneva', 'Attributes': ['T', 'I', 'W'], 'Periods': 10, 'PeriodDuration': 24}
# Set scenario
scenario = dict()
scenario['Objective'] = 'TOTEX'
scenario['EMOO'] = {}
scenario['specific'] = []
scenario['name'] = 'totex'
scenario['exclude_units'] = ['ThermalSolar']
scenario['enforce_units'] = []
# Set method options
method = {'building-scale': True}
# Initialize available units and grids
grids = infrastructure.initialize_grids()
units = infrastructure.initialize_units(scenario, grids)
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, cluster=cluster, scenario=scenario, method=method, solver="highs")
reho.single_optimization()
if save_results:
reho.save_results(format=['xlsx', 'pickle'], filename='test_results')
# Plot results
plotting.plot_sankey(reho.results['totex'][0], label='EN_long', color='ColorPastel', title="Sankey diagram", filename="figures/Sankey").show()
except ImportError as e:
pytest.fail(f"Running REHO failed: {e}")
import os
import pandas as pd
import pytest
from reho.test.test_run import test_run
from reho.plotting import plotting
@pytest.fixture(scope="module", autouse=True)
def generate_test_results():
if not os.path.exists('results/test_results.pickle'):
test_run(save_results=True)
@pytest.fixture(scope="module")
def results():
return pd.read_pickle('results/test_results.pickle')
def test_plot_performance(results):
try:
plotting.plot_performance(results, plot='costs', indexed_on='Scn_ID', title="Economical performance").show()
plotting.plot_performance(results, plot='gwp', indexed_on='Scn_ID', title="Environmental performance").show()
plotting.plot_performance(results, plot='combined', indexed_on='Scn_ID', title="Combined performance (Economical + Environmental)").show()
except ImportError as e:
pytest.fail(f"plot_performance failed: {e}")
def test_plot_expenses(results):
try:
plotting.plot_expenses(results, plot='costs', indexed_on='Scn_ID', title="Costs and Revenues").show()
except ImportError as e:
pytest.fail(f"plot_expenses failed: {e}")
def test_plot_sankey(results):
try:
plotting.plot_sankey(results['totex'][0], label='EN_long', color='ColorPastel', title="Sankey diagram").show()
except ImportError as e:
pytest.fail(f"plot_sankey failed: {e}")
def test_plot_eud(results):
try:
plotting.plot_eud(results, label='EN_long', title="End-use demands").show()
except ImportError as e:
pytest.fail(f"plot_eud failed: {e}")
def test_plot_profiles(results):
try:
units_to_plot = ['ElectricalHeater', 'HeatPump', 'PV', 'NG_Boiler']
plotting.plot_profiles(results['totex'][0], units_to_plot, label='EN_long', color='ColorPastel', resolution='weekly',
title="Energy profiles with a weekly moving average").show()
except ImportError as e:
pytest.fail(f"plot_profiles failed: {e}")
Set building parameters#
Each building needs to be characterized to estimate its energy demand, its renewable potential, and its sector coupling potential. Such information about the buildings involved in the analysis can be provided to REHO in two different ways:
By connecting to the QBuildings database ;
By reading CSV files.
QBuildings#
QBuildings is a GIS database for the characterization of the Swiss building stock from an energy point of view (end-use demand, buildings morphology, endogenous resources). It is built by gathering different public databases and combining them with SIA norms. It was initiated and developed by EPFL (Switzerland), within the Industrial Process and Energy Systems Engineering (IPESE) group.
REHO can connect to QBuildings and read the data it contains with the following code:
reader = QBuildingsReader() # load QBuildingsReader class
reader.establish_connection('Geneva') # connect to QBuildings database
qbuildings_data = reader.read_db(district_id=71, egid=['1009515']) # read data
See reho.model.preprocessing.QBuildings.QBuildingsReader.read_db
for further description.
Warning
The QBuildings-Suisse database will soon be available for full access. At present, you need to be connected to EPFL intranet to access the complete database.
However, a reduced version (QBuildings-Geneva) is already available to the public and serves as a demo for all the examples.
CSV files#
The buildings information can also be provided through a CSV file, with the call:
reader = QBuildingsReader()
qbuildings_data = reader.read_csv(buildings_filename='data/buildings.csv', nb_buildings=2)
See reho.model.preprocessing.QBuildings.QBuildingsReader.read_csv
for further description.
Warning
To work properly, the .csv given should contain the same fields as the ones defined in QBuildings.
The order does not matter. It can be helpful to explore the files scripts/examples/data/buildings.csv
,
scripts/examples/data/roofs.csv
and scripts/examples/data/facades.csv
.
Buildings input data#
List of buildings parameters
Parameters |
Description |
Example |
---|---|---|
id_class |
Buildingâs class, from tbl-sia380. If several, separate them with / |
I/II/I |
ratio |
Share of the ERA attributed to each id_class. If one class should be 1, else should follow the order of the id_class |
0.4/0.25/0.35 |
status |
From SIA2024, characterize the electricity consumption in REHO. Put âstandardâ by default. |
standard |
area_era_m2 |
Energetic Reference Area |
279.4 |
area_facade_m2 |
area of vertical facades |
348 |
area_roof_solar_m2 |
Roof area suitable for solar panels installation. See Sonnendach |
148.3 |
height_m |
Height up to the last ceiling. Use to determine shadowing in use_facades. |
12.83 |
thermal_transmittance_signature_kW_m2_K |
Averaged conductance |
0.00202 |
thermal_specific_capacity_Wh_m2_K |
Thermal inertia |
119.4 |
temperature_interior_C |
Target temperature to reach |
20.0 |
temperature_cooling_supply_C |
12.0 |
|
temperature_cooling_return_C |
17.0 |
|
temperature_heating_supply_C |
65.0 |
|
temperature_heating_return_C |
50.0 |
List of roofs parameters
Parameters |
Description |
Example |
---|---|---|
tilt |
Inclination of the roof, in degree |
30 |
azimuth |
Orientation of the roof, in degree |
12 |
id_roof |
Unique identifier |
1 |
area_roof_solar_m2 |
Surface suitable for solar panels |
210.3 |
id_building |
Use to identify to which building the roof belongs |
10 |
List of facades parameters
Parameters |
Description |
example of value |
---|---|---|
azimuth |
Orientation of the roof, in degree |
12 |
id_facade |
Unique identifier |
1 |
area_facade_solar_m2 |
Surface suitable for solar panels |
145.6 |
id_building |
Use to identify to which building the roof belongs |
10 |
cx |
Coordinate x of the facade centroid |
2592822.33 |
cy |
Coordinate y of the facade centroid |
2592809.46 |
geometry |
Geometry of the facade, useful if centroid is not available. Should be in wkb or wkt format. |
MULTILINESTRING ((2592822 1120151, 2592809 1120182)) |
Select weather data#
Based on the buildingâs coordinates, REHO automatically connects to the PVGIS dabatase (using the pvlib library) to extract annual weather data.
Yearly weather data is then clustered into typical days. The cluster
dictionary contains the clustering specifications:
cluster = {'Location': 'Geneva', 'Attributes': ['T', 'I', 'W'], 'Periods': 10, 'PeriodDuration': 24}
Where:
âLocationâ will be the name of the directory where clustering files are written.
âAttributesâ indicates the features among which the clustering is applied (T refers to Temperature, I to Irradiance, and W to Weekday).
âPeriodsâ relates to the desired number of typical periods.
âPeriodDurationâ is the typical period duration (24h is the default choice, corresponding to a typical day).
Note
scripts/examples/3f_Custom_profiles.py
shows how to provide custom weather data.
Set scenario#
Objective function#
REHO offers single or multi-objective optimization. The objective function can be specified in the scenario
dictionary:
scenario['Objective'] = 'TOTEX' # select an objective function as defined in ampl_model/scenario.mod
scenario['Objective'] = ['OPEX', 'CAPEX'] # for multi-objective optimization two objectives need to be specified
This scenario
dictionary can also be used to specify epsilon constraints (EMOO
) or additional constraints (specific
).
Epsilon constraints#
The key EMOO
allows to add an epsilon constraint on some objective:
scenario['EMOO'] = {EMOO_opex: 16} # select an epsilon constraint as defined in ampl_model/scenario.mod
This is used to limit another objective when performing multi-objective optimization.
In this example, the maximal allowed OPEX value is set to 16 [CHF/m2/y].
You can find a list of possible epsilon constraints in scenario.mod
.
Specific constraints#
In scenario
the key specific
allows to provide a list of specific constraints that can be activated:
scenario['specific'] = ["enforce_PV_max"] # enforce the entire roof surface to be covered with PV panels
Pareto curves#
To generate a Pareto front, 2 objective functions need to be specified:
scenario['Objective'] = ['OPEX', 'CAPEX'] # for multi-objective optimization two objectives are needed
The number of intermediate points for each objective is specified with:
scenario['nPareto'] = 2 # number of points per objective
The total number of optimizations will be 2 + 2 * nPareto
(2 extreme points plus 2 times a discretized interval of nPareto
points.
Note
Examples 1b_building-scale_Pareto.py
and 2b_district-scale_Pareto.py
can be run to obtain an OPEX-CAPEX Pareto front, at building-scale or district-scale respectively.
Initialize available units and grids#
Initializing the energy system structure is done with the reho.model.infrastructure.infrastructure
class.
Default values for units and grids are proposed, but any parameters can be adapted through providing customized .csv files.
Grids#
Grids are initialized with:
grids = infrastructure.initialize_grids(file="reho/data/infratructure/layers.csv")
Where the file layers.csv
contains the default parameters for the different energy layers available.
To use custom prices, there are two options:
Provide another .csv file to the
initialize_grids()
function:
grids = infrastructure.initialize_grids(file="my_custom_layers.csv")
Use the
Cost_supply_cst
andCost_demand_cst
parameters in theinitialize_grids()
function:
grids = infrastructure.initialize_grids({
'Electricity': {'Cost_supply_cst': 0.30, 'Cost_demand_cst': 0.18},
'Oil': {'Cost_supply_cst': 0.16}
})
In this example, new supply and demand costs for electricity, and a new supply cost oil are specified.
For further explanation, see reho.model.infrastructure.initialize_grids
.
Units#
Units are initialized with:
scenario['exclude_units'] = ['ThermalSolar']
scenario['enforce_units'] = ['HeatPump_Air']
units = infrastructure.initialize_units(scenario, grids, building_data="reho/data/infratructure/building_units.csv")
Where:
scenario['exclude_units']
is a list containing the units excluded from the available technologies.scenario['enforce_units']
is a list containing the units forced to be installed.The unit name has to match the Unit column of
building_units.csv
.If you do not want to exclude or enforce any unit, give empty lists.
grids
is the dictionary formerly returned byinitialize_grids()
.building_units.csv
contains the default specifications for units (cost, carbon footprintâŠ).
District units can be enabled with the argument district_data
:
units = infrastructure.initialize_units(scenario, grids, building_data, district_data="district_units.csv")
Here district_units.csv
contains the default parameters for district-size units.
Set method options#
You can use different methodology options in REHO, specified in the method
dictionary.
The methods available are listed in List of the available methods in REHO.
Method name |
Description |
Default behavior |
---|---|---|
Solar methods |
||
use_facades |
Allows to consider the facades for PV panels installation |
False |
use_pv_orientation |
Considers the orientation for the solar potential estimation, including a shadow model from neighbor buildings |
False |
Optimization methods |
||
building-scale |
Optimizes by considering than each building is an independent system |
False |
district-scale |
Optimizes by allowing exchanges between buildings and the use of district units |
False |
parallel_computation |
Allows to solve sub-problems in parallel |
True |
switch_off_second_objective |
To generate the Pareto curve by minimizing only one objective and constraining the other one. By default, both objectives are successively minimized and constrained. |
False |
Profiles |
||
include_stochasticity |
Includes variability among SIA typical consumption profiles |
False |
sd_stochasticity |
If include_stochasticity is True, specify the variability parameters through a list [sd_consumption, sd_timeshift] where sd_consumption is the standard deviation on the profile value, and sd_timeshift is the standard deviation on the profile time shift |
None |
use_dynamic_emission_profiles |
Uses hourly values for electricity GWP |
False |
use_custom_profiles |
Allows to replace SIA profiles for DHW [L/h], electricity demands [W/h] and people gains [W/h] by custom ones, via a dictionary where the key is among [âelectricityâ, âdhwâ, âoccupancyâ] and the value is the path to the file |
False |
Saving options |
||
include_all_solutions |
For a district-scale optimization, gives the results from the SPs |
False |
save_input_data |
Adds in the results file the input data (df_Buildings, df_Weather, df_Index) |
True |
save_timeseries |
Adds in the results file the timeseries results (df_Buildings_t and df_Unit_t) |
True |
save_streams |
Adds in the results file the streams-timeseries results (df_Streams_t) |
False |
extract_parameters |
To extract all the parameters used in the optimization |
False |
print_logs |
Prints the logs of the optimization(s) |
True |
Other |
||
actors_problem |
Changes the MP to solve: instead of considering the district as a single entity to optimize, different stakeholders portfolios are considered where the objective function is the minimization of the costs for one particular actor, while the costs of the other actors are constrained with parameterized epsilon values |
False |
DHN_CO2 |
To use CO2 in the DHN as heat carrier (default fluid is water) |
False |
interperiod_storage |
Allows the usage of long-term storage units |
False |
Optimization scope#
The value of REHO is to offer optimization of a specified territory at building-scale or district-scale.
Conduct a building-scale optimization, by setting:
method = {'building-scale': True}
Conduct a district-scale optimization, by setting:
method = {'district-scale': True}
PV orientation and PV on facades#
These lines of code will enable PV orientation and PV on facades:
reader = QBuildingsReader(load_roofs=True, load_facades=True)
reader.establish_connection('Suisse')
qbuildings_data = reader.read_db(district_id=3658, nb_buildings=2)
method = {'use_pv_orientation': True, 'use_facades': True, 'district-scale': True}
Warning
As the roofs and facades data are required, load_roofs
and load_facades
have been set to True in the reader a priori.
Run optimization#
The reho
instance is initialized with:
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, cluster=cluster, scenario=scenario, method=method, solver="highs")
One or several optimization(s) can then be conducted:
reho.single_optimization()
reho.generate_pareto_curve()
Save results#
At the end of the optimization process, the results are written in reho.results
, a dictionary indexed on Scn_ID
and Pareto_ID
.
These results can be saved as a .pickle or .xlsx file with:
reho.save_results(format=['pickle', 'xlsx'], filename='test_results')
Read results#
Saved results can be accessed with:
results = pd.read_pickle('test_results.pickle')
And browsing through Scn_ID
and Pareto_ID
with:
Scn_ID = list(results.keys())
Pareto_ID = list(results[Scn_ID[0]].keys())
df_Results = results[Scn_ID[0]][Pareto_ID[0]]
Where df_Results
corresponds to the output of one single-optimization, and is a dictionary containing the following dataframes: df_Performance
, df_Annuals
, df_Buildings
, df_Unit
, df_Unit_t
, df_Grid_t
, df_Buildings_t
, df_Time
, df_Weather
, df_Index
, df_KPIs
, df_Economics
.
Refer to reho.model.postprocessing.write_results.py
for more information about the content of these dataframes.
Plot results#
REHO embeds predefined plotting functions to visualize results, such as:
# Performance plot : Costs and Global Warming Potential
plotting.plot_performance(results, plot='costs', indexed_on='Scn_ID', filename="figures/performance_costs").show()
plotting.plot_performance(results, plot='gwp', indexed_on='Scn_ID', filename="figures/performance_gwp").show()
# Sankey diagram
plotting.plot_sankey(results['totex'][0], label='EN_long', color='ColorPastel').show()
Refer to reho.plotting.plotting
for more details and other plotting functions.