Examples#
This section reproduces the examples provided in the repository (these examples scripts are available in IPESE/REHO).
They should give you a brief overview of REHO’s capabilities and to test the various features of the tool.
Note
Since the content of the scripts/examples/
subfolder is git-tracked, you should not modify these files directly, but rather copy their contents into any other subfolder of scripts/
that you have yourself created. The content there (code, data, results, and figures) will be ignored by the git versioning.
1. Building-scale#
Single-optimization#
from reho.model.reho import *
from reho.plotting import plotting
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, nb_buildings=1)
# 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['name'] = 'totex'
scenario['exclude_units'] = []
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="gurobi")
reho.single_optimization()
plotting.plot_sankey(reho.results['totex'][0], label='EN_long', color='ColorPastel', title="Sankey diagram").show()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='1a')
Pareto curve#
from reho.model.reho import *
from reho.plotting import plotting
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, nb_buildings=1)
# Select clustering options for weather data
cluster = {'Location': 'Geneva', 'Attributes': ['T', 'I', 'W'], 'Periods': 10, 'PeriodDuration': 24}
# Set scenario
scenario = dict()
scenario['Objective'] = ['OPEX', 'CAPEX'] # for multi-objective optimization two objectives are needed
scenario['nPareto'] = 2 # number of points per objective (total number of optimizations = nPareto * 2 + 2)
scenario['name'] = 'pareto'
scenario['exclude_units'] = ['OIL_Boiler', '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="gurobi")
reho.generate_pareto_curve() # multi-objective optimization
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='1b')
# Performance plot : costs and gwp
plotting.plot_performance(reho.results, plot='costs', indexed_on='Pareto_ID', label='EN_long', title="Economical performance").show()
plotting.plot_performance(reho.results, plot='gwp', indexed_on='Pareto_ID', label='EN_long', title="Environmental performance").show()
# Sankey diagram
for key in reho.results['pareto'].keys():
plotting.plot_sankey(reho.results['pareto'][key], label='EN_long', color='ColorPastel', title="Sankey diagram").show()
2. District-scale#
Single-optimization#
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
# 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['name'] = 'totex'
scenario['exclude_units'] = []
scenario['enforce_units'] = []
# Set method options
method = {'district-scale': True}
DW_params = {'max_iter': 2}
# 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, DW_params=DW_params, solver="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='2a')
Pareto curve#
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, nb_buildings=2)
# Select clustering options for weather data
cluster = {'Location': 'Geneva', 'Attributes': ['T', 'I', 'W'], 'Periods': 10, 'PeriodDuration': 24}
# Set scenario
scenario = dict()
scenario['Objective'] = ['OPEX', 'CAPEX']
scenario['nPareto'] = 2
scenario['name'] = 'pareto'
scenario['exclude_units'] = ['OIL_Boiler']
scenario['enforce_units'] = []
# Set method options
method = {'district-scale': True}
DW_params = {'max_iter': 2}
# 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, DW_params=DW_params, solver="gurobi")
reho.generate_pareto_curve()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='2b')
3. Specific features#
Load buildings from a .csv file#
from reho.model.reho import *
if __name__ == '__main__':
buildings_filename = str(Path(__file__).parent / 'data' / 'buildings.csv')
# Set building parameters
# Load your buildings from a csv file instead of reading the database
reader = QBuildingsReader()
qbuildings_data = reader.read_csv(buildings_filename=buildings_filename, nb_buildings=2)
# Select clustering options for weather data
cluster = {'Location': 'Sion', 'Attributes': ['T', 'I', 'W'], 'Periods': 10, 'PeriodDuration': 24}
# Set scenario
scenario = dict()
scenario['Objective'] = 'TOTEX'
scenario['name'] = 'totex'
scenario['exclude_units'] = []
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="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3a')
Add diverse energy layers#
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
# 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['name'] = 'totex'
scenario['exclude_units'] = []
scenario['enforce_units'] = []
# Initialize available units and grids
# You can add more resources layers besides electricity and natural gas, and adapt their prices
# - directly within the script
# - or through a custom csv file based on the default values from data/infrastructure/layers.csv
grids = infrastructure.initialize_grids({'Electricity': {"Cost_supply_cst": 0.30, "Cost_demand_cst": 0.16},
'NaturalGas': {"Cost_supply_cst": 0.15},
'Wood': {},
'Oil': {},
})
# Set method options
method = {'building-scale': True}
# Units specifications can also be adapted through a custom csv file based on the default values from data/infrastructure/building_units.csv
# You can simply create a new file and specify the path to it in the initialize_units function
path_to_custom_units = str(Path(__file__).parent / 'data' / 'custom_building_units.csv')
units = infrastructure.initialize_units(scenario, grids, building_data=path_to_custom_units)
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3b')
Change heat pump temperature#
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
n_buildings = len(qbuildings_data['buildings_data'])
# 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['name'] = 'totex'
scenario['exclude_units'] = []
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)
# Set specific parameters
# Heat pump can have different sources such as air, lake, geothermal
parameters = {"T_source": np.repeat({"Geothermal": 17.0}, n_buildings)}
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, parameters=parameters, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3c')
Include electric vehicles#
from reho.plotting import plotting
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
# 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['name'] = 'totex'
scenario['exclude_units'] = ['Battery', 'Bike_district', 'ICE_district', 'ElectricBike_district']
scenario['enforce_units'] = []
parameters = dict()
# Initialize available units and grids
grids = infrastructure.initialize_grids({'Electricity': {},
'NaturalGas': {},
'Gasoline': {},
'Mobility': {},
})
units = infrastructure.initialize_units(scenario, grids, district_data=True)
# Set method options
method = {'building-scale': True}
# Set specific parameters
parameters = {}
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, cluster=cluster, scenario=scenario, method=method, parameters=parameters, solver="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3d')
# Plot results
plotting.plot_performance(reho.results, plot='costs', indexed_on='Scn_ID', label='EN_long', title="Economical performance").show()
Integrate a district heating network#
from reho.model.reho import *
from reho.plotting import plotting
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, nb_buildings=4)
# 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['name'] = 'totex'
scenario['exclude_units'] = []
scenario['enforce_units'] = ['HeatPump_DHN']
scenario["specific"] = ["enforce_DHN"]
# Set method options
# You can specify if the DHN is based on CO2. If not, a water DHN is assumed.
method = {'building-scale': True, 'DHN_CO2': True}
# Set specific parameters
# Specify the temperature of the DHN
parameters = {'T_DHN_supply_cst': np.repeat(20.0, 4), "T_DHN_return_cst": np.repeat(15.0, 4)}
# Initialize available units and grids
grids = infrastructure.initialize_grids({'Electricity': {},
'NaturalGas': {},
'Heat': {}})
units = infrastructure.initialize_units(scenario, grids, district_data=True)
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, parameters=parameters, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
reho.get_DHN_costs() # run one optimization forcing DHN to find costs DHN connection per house
reho.single_optimization() # run optimization with DHN costs
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3e')
# Plot results
plotting.plot_performance(reho.results, plot='costs', indexed_on='Scn_ID', label='EN_long', title="Economical performance").show()
plotting.plot_sankey(reho.results['totex'][0], label='EN_long', color='ColorPastel', title="Sankey diagram").show()
Use custom profiles#
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
# Select clustering options for weather data, with custom profiles
custom_weather_profile = str(Path(__file__).parent / 'data' / 'profiles' / 'Geneva.csv')
cluster = {'custom_weather': custom_weather_profile, 'Location': 'Geneva', 'Attributes': ['T', 'I', 'W'], 'Periods': 10, 'PeriodDuration': 24}
# Set scenario
scenario = dict()
scenario['Objective'] = 'TOTEX'
scenario['name'] = 'totex'
scenario['exclude_units'] = []
scenario['enforce_units'] = []
# Set method options
# You can provide here a profile for domestic electricity, domestic hot water, or building occupancy
custom_elec_profile = str(Path(__file__).parent / 'data' / 'profiles' / 'electricity.csv')
method = {'building-scale': True, 'use_custom_profiles': {'electricity': custom_elec_profile}}
# Initialize available units and grids
grids = infrastructure.initialize_grids()
units = infrastructure.initialize_units(scenario, grids=grids)
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3f')
Include stochasticity into profiles#
from reho.model.reho import *
from reho.model.preprocessing.QBuildings import *
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
# 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['name'] = 'totex'
scenario['exclude_units'] = []
scenario['enforce_units'] = []
# Set method options
# Add stochasticity in the demand profiles given by the SIA standards, tunable with:
# - standard deviation on the peak demand
# - standard deviation on the time-shift
method = {'building-scale': True, 'include_stochasticity': True, 'sd_stochasticity': [0.1, 2]}
# 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="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3g')
Fix units size#
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
# 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['name'] = 'totex'
scenario['exclude_units'] = []
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="gurobi")
reho.single_optimization()
# Run a new optimization with the capacity of PV and electrical heater fixed with the size of the first optimization
reho.df_fix_Units = reho.results['totex'][0]["df_Unit"] # load data on the capacity of units
reho.fix_units_list = ['PV', 'ElectricalHeater_DHW', 'ElectricalHeater_SH'] # select the ones being fixed
reho.scenario['Objective'] = 'CAPEX'
reho.scenario['name'] = 'fixed'
reho.method['fix_units'] = True # select the method fixing the unit sizes
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3h')
Connect to ELCOM database for electricity prices#
from reho.model.reho import *
from reho.model.preprocessing import electricity_prices
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
# 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['name'] = 'totex'
scenario['exclude_units'] = []
scenario['enforce_units'] = []
# Set method options
method = {'building-scale': True}
# Initialize available units and grids
# You can use prices coming from the ELCOM public database
prices = electricity_prices.get_prices_from_elcom_by_city(city=reader, category='H4')
grids = infrastructure.initialize_grids({'Electricity': {"Cost_supply_cst": prices['finalcosts'][0], "Cost_demand_cst": 0.16},
'NaturalGas': {"Cost_supply_cst": 0.15},
})
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="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='3i')
Include capacities of networks for imports and exports#
4. Global features#
Compare various scenarios#
from reho.model.reho import *
from reho.plotting import plotting
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, egid=['1017073/1017074', '1017109', '1017079', '1030377/1030380'])
# 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'] = []
# Set method options
method = {'building-scale': True}
# Set specific parameters
parameters = {}
# Scenario 1 Oil boiler
scenario['name'] = 'Oil'
scenario['exclude_units'] = ['ThermalSolar', 'HeatPump', 'ElectricalHeater', 'PV']
scenario['enforce_units'] = []
grids = infrastructure.initialize_grids({'Electricity': {}, 'Oil': {}})
units = infrastructure.initialize_units(scenario, grids)
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, parameters=parameters, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
reho.single_optimization()
# Scenario 2 HP + PV
scenario['name'] = 'HP + PV'
scenario['exclude_units'] = ['ThermalSolar', 'OIL_Boiler']
scenario['enforce_units'] = []
units = infrastructure.initialize_units(scenario, grids)
reho.scenario = scenario
reho.units = units
reho.infrastructure = infrastructure.Infrastructure(qbuildings_data, units, grids)
reho.build_infrastructure_SP()
for b in qbuildings_data['buildings_data']:
reho.buildings_data[b]['Th_supply_0'] = 45
reho.buildings_data[b]['Th_return_0'] = 35
reho.single_optimization()
# Scenario 3 EV
scenario['name'] = 'EV'
scenario['exclude_units'] = ['ThermalSolar', 'OIL_Boiler', 'Bike_district', 'ICE_district', 'ElectricBike_district']
scenario['enforce_units'] = ['EV_district']
grids = infrastructure.initialize_grids({'Electricity': {}, 'Oil': {}, 'Gasoline': {}, 'Mobility': {}})
units = infrastructure.initialize_units(scenario, grids, district_data=True)
reho.scenario = scenario
reho.units = units
reho.infrastructure = infrastructure.Infrastructure(qbuildings_data, units, grids)
reho.build_infrastructure_SP()
reho.single_optimization()
# Scenario 4 ICT
scenario['name'] = 'ICT'
scenario['exclude_units'] = ['ThermalSolar', 'OIL_Boiler', 'Bike_district', 'ICE_district', 'ElectricBike_district', 'DataHeat_SH']
scenario['enforce_units'] = ['EV_district', 'DataHeat_DHW']
grids = infrastructure.initialize_grids({'Electricity': {}, 'Oil': {}, 'Gasoline': {}, 'Mobility': {},
'Data': {"Cost_demand_cst": 1, "GWP_demand_cst": 0}})
units = infrastructure.initialize_units(scenario, grids, district_data=True)
reho.scenario = scenario
reho.units = units
reho.infrastructure = infrastructure.Infrastructure(qbuildings_data, units, grids)
reho.build_infrastructure_SP()
reho.single_optimization()
# Scenario 5 Isolation
scenario['name'] = 'Isolation'
for b in qbuildings_data['buildings_data']:
reho.buildings_data[b]['U_h'] = 0.4 * qbuildings_data['buildings_data'][b]['U_h']
reho.scenario = scenario
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='4a')
# Additional data
era = reho.results['Oil'][0]['df_Buildings'].ERA.sum()
# Gasoline avoided costs = EV_consumption * 4 (efficiency ratio ICE/EV) * gasoline_price
gasoline_price = 0.24 # CHF/kWh
gasoline_gwp = 0.32 # kgCO2/kWh
EV_consumption = reho.results['EV'][0]['df_Annuals'].loc[("Electricity", "EV_charger_district"), "Demand_MWh"] - reho.results['EV'][0]['df_Annuals'].loc[("Electricity", "EV_charger_district"), "Supply_MWh"]
gasoline_cost = 1000 * EV_consumption * 4 * gasoline_price / era
gasoline_impact = 1000 * EV_consumption * 4 * gasoline_gwp / era
# ICT avoided costs = ICT_consumption * 1.3 (mean PUE for Switzerland) * electricity_price
electricity_price = 0.33 # CHF/kWh
electricity_gwp = 0.13 # kgCO2/kWh
ict_cost = 1000 * reho.results['ICT'][0]['df_Annuals'].loc[("Data", "Network"), "Demand_MWh"] * 1.3 * electricity_price / era
ict_impact = 1000 * reho.results['ICT'][0]['df_Annuals'].loc[("Data", "Network"), "Demand_MWh"] * 1.3 * electricity_gwp / era
# Isolation costs and impact
isolation_cost = 5.4 # CHF/m2/yr (already annualized for 50 years)
isolation_impact = 0.076 # kgCO2/m2/yr (already annualized for 50 years)
additional_costs = {'mobility': [gasoline_cost, gasoline_cost, 0, 0, 0],
'ict': [ict_cost, ict_cost, ict_cost, 0, 0],
'isolation': [0, 0, 0, 0, isolation_cost]}
additional_costs['no_ict_profit'] = False # data processing profits can be included in the costs or not
additional_gwp = {'mobility': [gasoline_impact, gasoline_impact, 0, 0, 0],
'ict': [ict_impact, ict_impact, ict_impact, 0, 0],
'isolation': [0, 0, 0, 0, isolation_impact]}
# Plot results
plotting.plot_performance(reho.results, plot='costs', per_m2=True, additional_costs=additional_costs, title="Economical performance").show()
plotting.plot_performance(reho.results, plot='gwp', per_m2=True, additional_gwp=additional_gwp, title="Environmental performance").show()
Conduct a sensitivity analysis#
from reho.model.postprocessing.sensitivity_analysis import *
from reho.plotting import plotting
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=234, nb_buildings=1)
# 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['name'] = 'totex'
scenario['exclude_units'] = []
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 sensitivity analysis
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
SA = SensitivityAnalysis(reho, SA_type="Monte_Carlo", sampling_parameters=8)
SA_parameters = {'Elec_retail': [0.2, 0.45], 'Elec_feedin': [0.0, 0.15], 'NG_retail': [0.2, 0.4]}
SA.build_SA(unit_parameter=['Cost_inv1', 'Cost_inv2'], SA_parameters=SA_parameters)
SA.run_SA()
# Save results
plotting.plot_performance(reho.results, plot='costs', indexed_on='Pareto_ID', label='EN_long', title="Economical performance").show()
reho.save_results(format=['xlsx', 'pickle'], filename='4b')
5. Photovoltaics#
Consider roofs orientation#
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
# Roofs orientation for PV can be considered
reader = QBuildingsReader(load_roofs=True)
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=2, nb_buildings=2)
# 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['name'] = 'totex'
scenario['exclude_units'] = []
scenario['enforce_units'] = []
# Set method options
method = {'use_pv_orientation': 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="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='5a')
Include photovoltaics on facades#
from reho.model.reho import *
if __name__ == '__main__':
# Set building parameters
# PV on facades can be considered
reader = QBuildingsReader(load_facades=True, load_roofs=True)
# # Warning: to connect to QBuildings-Suisse (database including facades data), you need to be within EPFL intranet.
# reader.establish_connection('Suisse')
# qbuildings_data = reader.read_db(district_id=3658, nb_buildings=2)
# Alternatively, roof orientations and facades can be loaded from csv files
buildings_filename = str(Path(__file__).parent / 'data' / 'buildings.csv')
facades_filename = str(Path(__file__).parent / 'data' / 'facades.csv')
roofs_filename = str(Path(__file__).parent / 'data' / 'roofs.csv')
qbuildings_data = reader.read_csv(buildings_filename=buildings_filename, nb_buildings=2,
facades_filename=facades_filename, roofs_filename=roofs_filename)
# Select clustering options for weather data
cluster = {'Location': 'Sion', 'Attributes': ['T', 'I', 'W'], 'Periods': 10, 'PeriodDuration': 24}
# Set scenario
scenario = dict()
scenario['Objective'] = 'TOTEX'
scenario['name'] = 'totex'
scenario['exclude_units'] = []
scenario['enforce_units'] = []
# Set method options
method = {'use_pv_orientation': True, 'use_facades': True, '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="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='5b')
6. Mobility#
Add Mobility Layer#
The Layer Mobility differs slightly from the other Layers in REHO as this energy carrier is expressed in passenger-kilometers (\(pkm\)) rather than \(kWh\). The mobility demand is represented through an hourly passenger-kilometer (\(pkm\)) profile for each typical day, similarly to the other end-use demand profiles. The transport units represented in the model include EVs, ICEs, bikes, electric bikes and public transport. The model can optimize between the different transport modes. However, it is for now recommended to constrain the modal split, as the optimization based on cost does not reflect typical usage of the different transport modes. The FSO reports can be used to find suitable modal split data.
from reho.model.reho import *
from reho.plotting import plotting
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Suisse')
qbuildings_data = reader.read_db(district_id=234, nb_buildings=2)
# Select weather data
cluster = {'Location': 'Geneva', 'Attributes': ['I', 'T', 'W'], 'Periods': 10, 'PeriodDuration': 24}
# Set scenario
scenario = dict()
scenario['Objective'] = 'TOTEX'
scenario['EMOO'] = {}
scenario['exclude_units'] = []
scenario['enforce_units'] = ['EV_district']
# Initialize available units and grids
grids = infrastructure.initialize_grids({'Electricity': {},
'NaturalGas': {},
'Gasoline': {},
'Mobility': {},
})
units = infrastructure.initialize_units(scenario, grids, district_data=True)
# Set method options
method = {'building-scale': True}
# SCENARIO 1: Flexible charging profile
scenario['name'] = 'totex'
# Set parameters
era = np.sum([qbuildings_data["buildings_data"][b]['ERA'] for b in qbuildings_data["buildings_data"]])
# here Population is scaled to the number of buildings being optimized (CH : 46m²/cap on average )
# 35 km/cap/day, 2 categories of distance (D0 : short and D1 : long)
parameters = {"Population": era / 46, "DailyDist": {'D0': 25, 'D1': 10}}
# min max share for each mobility mode and each distance
modal_split = pd.DataFrame({"min_D0": [0, 0, 0.4, 0.3], "max_D0": [0.1, 0.3, 0.7, 0.7],
"min_D1": [0, 0.2, 0.4, 0.3], "max_D1": [0, 0.4, 0.7, 0.7]},
index=['MD', 'PT', 'cars', 'EV_district'])
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, parameters=parameters, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
reho.modal_split = modal_split # give modal_split as attribute
reho.single_optimization()
# SCENARIO 2: Fixed charging profile
scenario['name'] = 'totex_profile'
# Activate the constraint forcing the charging profile of electric vehicles.
scenario['specific'] = ['EV_chargingprofile1', "EV_chargingprofile2"]
# Run optimization
reho.scenario = scenario
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='6a')
# Plot results
plotting.plot_performance(reho.results, plot='costs', indexed_on='Scn_ID', label='EN_long', title="Economical performance").show()
Co-optimization#
Multiple districts can be optimized together in order to calculate EV charging exchanges between districts. This feature can be used to conduct analyses on EV fleets at the city scale. Example 6b demonstrates how to use this feature step by step. Only one district is optimized with external charging option available. The optimized district is also parameterized with a load on EV charger representing incoming EVs from other districts.
7. Interperiod storage#
Investigate interperiod storage units in a building facing grid constraints (e.g. a building with limited import or export capacity).
Hydrogen and biomethane storage#
from reho.model.reho import *
from reho.plotting import plotting
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=5, egid=['2034144/2034143/2749579/2034146/2034145'])
# 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['name'] = 'totex'
scenario['exclude_units'] = ["FC", "ETZ", "Battery_IP"]
scenario['enforce_units'] = ["rSOC", "MTR", "CO2_storage_IP", "CH4_storage_IP"]
# Set method options
method = {'interperiod_storage': True}
# Initialize available units and grids
# WARNING: necessary to define all 3 layers Hydrogen / Biomethane / CO2 to enable rSOC or Methanator unit
grids = infrastructure.initialize_grids({'Electricity': {},
'NaturalGas': {},
'Hydrogen': {},
'Biomethane': {},
'CO2': {},
})
grids["Electricity"]["ReinforcementOfNetwork"] = np.array([5]) # limit the 2000 kW default value (from layers.csv) for export or import electricity
grids["Hydrogen"]["ReinforcementOfNetwork"] = np.array([0]) # keep the 0 kW default value (from layers.csv) for export or import hydrogen
units = infrastructure.initialize_units(scenario, grids, interperiod_data=True) # enable interperiod storage
# Set parameters
parameters = {}
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, parameters=parameters, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='7a')
# Plot results
plotting.plot_performance(reho.results, plot='costs', indexed_on='Scn_ID', label='EN_long', title="Economical performance").show()
plotting.plot_sankey(reho.results['totex'][0], label='EN_long', color='ColorPastel', title="Sankey diagram").show()
plotting.plot_electricity_flows(reho.results['totex'][0], color='ColorPastel', day_of_the_year=40, time_range='2 weeks', label='EN_long').show()
plotting.plot_storage_profile(reho.results['totex'][0], resolution='hourly').show()
Hydrogen production and export#
from reho.model.reho import *
from reho.plotting import plotting
if __name__ == '__main__':
# Set building parameters
reader = QBuildingsReader()
reader.establish_connection('Geneva')
qbuildings_data = reader.read_db(district_id=5, egid=['2034144/2034143/2749579/2034146/2034145'])
# 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['name'] = 'totex'
scenario['exclude_units'] = ["FC", "ETZ", "Battery_IP", "CO2_storage_IP", "CH4_storage_IP"]
scenario['enforce_units'] = ["rSOC"]
# Set method options
method = {'interperiod_storage': True}
# Initialize available units and grids
# WARNING: necessary to define all 3 layers Hydrogen / Biomethane / CO2 to enable rSOC or Methanator unit
grids = infrastructure.initialize_grids({'Electricity': {},
'NaturalGas': {},
'Hydrogen': {"Cost_supply_cst": 0.45, "Cost_demand_cst": 0.15}, # default export price = 0.15 CHF/kWh (5 CHF/kg H2)
'Biomethane': {},
'CO2': {},
})
grids["Electricity"]["ReinforcementOfNetwork"] = np.array([15]) # limit the 2000 kW default value (from layers.csv) for export or import electricity
grids["Hydrogen"]["ReinforcementOfNetwork"] = np.array([100]) # update the 0 kW default value (from layers.csv) for export or import hydrogen
units = infrastructure.initialize_units(scenario, grids, interperiod_data=True) # enable interperiod storage
# Set parameters
parameters = {}
# Annual hydrogen export can be forced in the parameters
# parameters['HydrogenAnnualExport'] = 20e3 # kWh
# scenario['specific'] = ['forced_H2_annual_export']
# A continuous daily hydrogen export can be forced (value is a variable in the optimization)
scenario['specific'] = ['forced_H2_fixed_daily_export']
# Run optimization
reho = REHO(qbuildings_data=qbuildings_data, units=units, grids=grids, parameters=parameters, cluster=cluster, scenario=scenario, method=method, solver="gurobi")
reho.single_optimization()
# Save results
reho.save_results(format=['xlsx', 'pickle'], filename='7b')
# Plot results
plotting.plot_performance(reho.results, plot='costs', indexed_on='Scn_ID', label='EN_long', title="Economical performance").show()
plotting.plot_sankey(reho.results['totex'][0], label='EN_long', color='ColorPastel', title="Sankey diagram").show()
plotting.plot_electricity_flows(reho.results['totex'][0], color='ColorPastel', day_of_the_year=40, time_range='2 weeks', label='EN_long').show()
plotting.plot_storage_profile(reho.results['totex'][0], resolution='weekly').show()