Compare commits
8 Commits
main
...
summercour
Author | SHA1 | Date | |
---|---|---|---|
7f539b1ca5 | |||
e56319ecd3 | |||
8c6715754a | |||
0769887868 | |||
3694f0c7c1 | |||
b03e4db053 | |||
51eebcc6ef | |||
81ac7bc0c3 |
95
costs/Individualplot.py
Normal file
95
costs/Individualplot.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
import plotly.graph_objects as go
|
||||
import matplotlib.pyplot as plt
|
||||
import plotly.express as px
|
||||
|
||||
def individualplot(output_yearly_graph,retrofitting_scenario) :
|
||||
# Sample data
|
||||
categories = output_yearly_graph.index
|
||||
bar_data_1 = output_yearly_graph['Capital']
|
||||
bar_data_2 = -output_yearly_graph['Capital incomes']
|
||||
bar_data_3 = output_yearly_graph['End of life']
|
||||
bar_data_4 = output_yearly_graph['Operational total']
|
||||
bar_data_5 = -output_yearly_graph['Operational income']
|
||||
line_data = output_yearly_graph['Common addition']
|
||||
|
||||
# Create bar trace 1
|
||||
bar_trace_1 = go.Bar(
|
||||
x=categories,
|
||||
y=bar_data_1,
|
||||
name='Capital',
|
||||
yaxis='y1'
|
||||
)
|
||||
|
||||
# Create bar trace 2
|
||||
bar_trace_2 = go.Bar(
|
||||
x=categories,
|
||||
y=bar_data_2,
|
||||
name='Capital incomes',
|
||||
yaxis='y1',
|
||||
marker=dict(color='red')
|
||||
)
|
||||
# Create bar trace 2
|
||||
bar_trace_3 = go.Bar(
|
||||
x=categories,
|
||||
y=bar_data_3,
|
||||
name='End of life',
|
||||
yaxis='y1'
|
||||
)
|
||||
# Create bar trace 2
|
||||
bar_trace_4 = go.Bar(
|
||||
x=categories,
|
||||
y=bar_data_4,
|
||||
name='Operational total',
|
||||
yaxis='y1'
|
||||
)
|
||||
# Create bar trace 2
|
||||
bar_trace_5 = go.Bar(
|
||||
x=categories,
|
||||
y=bar_data_5,
|
||||
name='Operational income',
|
||||
yaxis='y1',
|
||||
marker=dict(color='red')
|
||||
)
|
||||
|
||||
# Create line trace
|
||||
line_trace = go.Scatter(
|
||||
x=categories,
|
||||
y=line_data,
|
||||
mode='lines',
|
||||
name='Common addition',
|
||||
yaxis='y2'
|
||||
)
|
||||
|
||||
# Create layout
|
||||
layout = go.Layout(
|
||||
title='Stacked Bar Chart with Negative Values and Line',
|
||||
xaxis=dict(title='Categories'),
|
||||
yaxis=dict(title='Bar Values', side='left', showgrid=False),
|
||||
yaxis2=dict(title='Line Values', side='right', overlaying='y', showgrid=False),
|
||||
barmode='stack'
|
||||
)
|
||||
|
||||
# Create figure
|
||||
#fig = go.Figure(data=[bar_trace_1, bar_trace_2, bar_trace_3, bar_trace_4, bar_trace_5, line_trace], layout=layout)
|
||||
|
||||
#fig.show()
|
||||
|
||||
fig, ax1 = plt.subplots()
|
||||
bottom = [0]*len(bar_data_1)
|
||||
ax1.bar(categories, bar_data_1, label='Capital costs', color='green')
|
||||
ax1.bar(categories, bar_data_3, label='End of life costs', color='grey')
|
||||
ax1.bar(categories, bar_data_4, label='Operational costs', color='brown')
|
||||
ax1.bar(categories, bar_data_2, label='Capital incomes', color='red', bottom=bottom)
|
||||
ax1.bar(categories, bar_data_5, label='Operational incomes', color='orange', bottom=bar_data_2)
|
||||
|
||||
ax1.set_ylabel('Cost (CAD)')
|
||||
ax1.set_title('Yearly costs and cumulative costs (CAD)')
|
||||
ax1.legend()
|
||||
|
||||
# Create the line chart on a secondary y-axis
|
||||
ax2 = ax1.twinx()
|
||||
ax2.plot(categories, line_data, marker='o', linestyle='-', color='blue', label='Line')
|
||||
ax2.set_ylabel('Cumulative cost (CAD)')
|
||||
ax2.legend()
|
||||
|
||||
plt.show()
|
200
costs/LCC_calculation_scenarios.py
Normal file
200
costs/LCC_calculation_scenarios.py
Normal file
|
@ -0,0 +1,200 @@
|
|||
from pathlib import Path
|
||||
import numpy_financial as npf
|
||||
import pandas as pd
|
||||
from costs.printing_results import *
|
||||
from costs.Individualplot import *
|
||||
from costs.LCC_calculation_scenarios import *
|
||||
from costs.life_cycle_costs import LifeCycleCosts
|
||||
from hub.helpers import constants as cte
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
|
||||
from costs import ENERGY_SYSTEM_FORMAT, RETROFITTING_SCENARIOS, NUMBER_OF_YEARS
|
||||
from costs import CONSUMER_PRICE_INDEX, ELECTRICITY_PEAK_INDEX, ELECTRICITY_PRICE_INDEX, GAS_PRICE_INDEX, DISCOUNT_RATE
|
||||
|
||||
|
||||
def _search_archetype(costs_catalog, building_function):
|
||||
costs_archetypes = costs_catalog.entries('archetypes').archetypes
|
||||
for building_archetype in costs_archetypes:
|
||||
if str(building_function) == str(building_archetype.function):
|
||||
return building_archetype
|
||||
raise KeyError('archetype not found')
|
||||
def _npv_from_list(npv_discount_rate, list_cashflow):
|
||||
lcc_value = npf.npv(npv_discount_rate, list_cashflow)
|
||||
return lcc_value
|
||||
def LCC_calculation_scenarios(city, catalog, retrofitting_scenario, valuepareto, out_path, energy_outputs_for_graph) :
|
||||
Pareto = pd.DataFrame()
|
||||
investmentcosts = pd.DataFrame([])
|
||||
life_cycle_results = pd.DataFrame()
|
||||
total_floor_area = 0
|
||||
total_floor_area_dataframe = pd.DataFrame()
|
||||
for building in city.buildings:
|
||||
for energy_system in building.energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
energy_system.generation_system.heat_power = building.heating_peak_load[cte.YEAR][0]
|
||||
if cte.COOLING in energy_system.demand_types:
|
||||
energy_system.generation_system.cooling_power = building.cooling_peak_load[cte.YEAR][0]
|
||||
|
||||
print(f'beginning costing scenario {retrofitting_scenario} systems... done')
|
||||
|
||||
for building in city.buildings:
|
||||
function = Dictionaries().hub_function_to_montreal_custom_costs_function[building.function]
|
||||
archetype = _search_archetype(catalog, function)
|
||||
if "gas" in building.energy_systems_archetype_name:
|
||||
FUEL_TYPE = 1
|
||||
else:
|
||||
FUEL_TYPE = 0
|
||||
lcc = LifeCycleCosts(building, archetype, NUMBER_OF_YEARS, CONSUMER_PRICE_INDEX, ELECTRICITY_PEAK_INDEX,
|
||||
ELECTRICITY_PRICE_INDEX, GAS_PRICE_INDEX, DISCOUNT_RATE, retrofitting_scenario, FUEL_TYPE)
|
||||
global_capital_costs, global_capital_incomes = lcc.calculate_capital_costs()
|
||||
global_end_of_life_costs = lcc.calculate_end_of_life_costs()
|
||||
global_operational_costs = lcc.calculate_total_operational_costs()
|
||||
global_maintenance_costs = lcc.calculate_total_maintenance_costs()
|
||||
global_operational_incomes = lcc.calculate_total_operational_incomes()
|
||||
|
||||
total_plot_costs = global_capital_costs - global_capital_incomes + global_end_of_life_costs + \
|
||||
global_operational_costs + global_maintenance_costs - global_operational_incomes
|
||||
|
||||
capital_total = global_capital_costs.sum(axis=1)
|
||||
capital_income_total = global_capital_incomes.sum(axis=1)
|
||||
end_of_life_total = global_end_of_life_costs.sum(axis=1)
|
||||
operational_total = global_operational_costs.sum(axis=1)
|
||||
maintenance_total = global_maintenance_costs.sum(axis=1)
|
||||
operational_income_total = global_operational_incomes.sum(axis=1)
|
||||
|
||||
lineatotal = capital_total - capital_income_total + end_of_life_total + operational_total + maintenance_total - \
|
||||
operational_income_total
|
||||
|
||||
lineatotal = lineatotal.cumsum()
|
||||
|
||||
output_yearly_graph = pd.DataFrame({'Capital': capital_total,
|
||||
'Capital incomes': capital_income_total,
|
||||
'End of life': end_of_life_total,
|
||||
'Operational total': operational_total,
|
||||
'Maintenance total': maintenance_total,
|
||||
'Operational income': operational_income_total, 'Common addition': lineatotal})
|
||||
|
||||
individualplot(output_yearly_graph, retrofitting_scenario)
|
||||
|
||||
full_path_output = Path(out_path / f'output_scenario_{retrofitting_scenario}_building_{building.name}.xlsx').resolve()
|
||||
|
||||
with pd.ExcelWriter(full_path_output) as writer:
|
||||
global_capital_costs.to_excel(writer, sheet_name='global_capital_costs')
|
||||
global_end_of_life_costs.to_excel(writer, sheet_name='global_end_of_life_costs')
|
||||
global_operational_costs.to_excel(writer, sheet_name='global_operational_costs')
|
||||
global_maintenance_costs.to_excel(writer, sheet_name='global_maintenance_costs')
|
||||
global_operational_incomes.to_excel(writer, sheet_name='global_operational_incomes')
|
||||
global_capital_incomes.to_excel(writer, sheet_name='global_capital_incomes')
|
||||
|
||||
print('RETROFITTING SCENARIO', retrofitting_scenario)
|
||||
if retrofitting_scenario == 0:
|
||||
investmentcosts = [global_capital_costs['B2010_opaque_walls'][0],
|
||||
global_capital_costs['B2020_transparent'][0],
|
||||
global_capital_costs['B3010_opaque_roof'][0],
|
||||
global_capital_costs['B10_superstructure'][0],
|
||||
global_capital_costs['D3020_heat_generating_systems'][0],
|
||||
global_capital_costs['D3080_other_hvac_ahu'][0],
|
||||
global_capital_costs['D5020_lighting_and_branch_wiring'][0],
|
||||
global_capital_costs['D301010_photovoltaic_system'][0]]
|
||||
investmentcosts = pd.DataFrame(investmentcosts)
|
||||
|
||||
else:
|
||||
investmentcosts[f'retrofitting_scenario_{retrofitting_scenario}'] = \
|
||||
[global_capital_costs['B2010_opaque_walls'][0],
|
||||
global_capital_costs['B2020_transparent'][0],
|
||||
global_capital_costs['B3010_opaque_roof'][0],
|
||||
global_capital_costs['B10_superstructure'][0],
|
||||
global_capital_costs['D3020_heat_generating_systems'][0],
|
||||
global_capital_costs['D3080_other_hvac_ahu'][0],
|
||||
global_capital_costs['D5020_lighting_and_branch_wiring'][0],
|
||||
global_capital_costs['D301010_photovoltaic_system'][0]]
|
||||
|
||||
investmentcosts.index = ['Opaque walls', 'Transparent walls', 'Opaque roof', 'Superstructure',
|
||||
'Heat generation systems', 'Other HVAC AHU', 'Lighting and branch wiring', 'PV systems']
|
||||
|
||||
investmentcosts = investmentcosts.applymap(lambda x: round(x, 2))
|
||||
|
||||
df_capital_costs_skin = (
|
||||
global_capital_costs['B2010_opaque_walls'] + global_capital_costs['B2020_transparent'] +
|
||||
global_capital_costs['B3010_opaque_roof'] + global_capital_costs['B10_superstructure']
|
||||
)
|
||||
df_capital_costs_systems = (
|
||||
global_capital_costs['D3020_heat_generating_systems'] +
|
||||
global_capital_costs['D3030_cooling_generation_systems'] +
|
||||
global_capital_costs['D3080_other_hvac_ahu'] +
|
||||
global_capital_costs['D5020_lighting_and_branch_wiring'] +
|
||||
global_capital_costs['D301010_photovoltaic_system']
|
||||
)
|
||||
df_end_of_life_costs = global_end_of_life_costs['End_of_life_costs']
|
||||
df_operational_costs = (
|
||||
global_operational_costs['Fixed_costs_electricity_peak'] +
|
||||
global_operational_costs['Fixed_costs_electricity_monthly'] +
|
||||
global_operational_costs['Variable_costs_electricity'] +
|
||||
global_operational_costs['Fixed_costs_gas'] +
|
||||
global_operational_costs['Variable_costs_gas']
|
||||
)
|
||||
df_maintenance_costs = (
|
||||
global_maintenance_costs['Heating_maintenance'] +
|
||||
global_maintenance_costs['Cooling_maintenance'] +
|
||||
global_maintenance_costs['PV_maintenance']
|
||||
)
|
||||
df_operational_incomes = global_operational_incomes['Incomes electricity']
|
||||
|
||||
df_capital_incomes = (
|
||||
global_capital_incomes['Subsidies construction'] +
|
||||
global_capital_incomes['Subsidies HVAC'] +
|
||||
global_capital_incomes['Subsidies PV']
|
||||
)
|
||||
|
||||
life_cycle_costs_capital_skin = _npv_from_list(DISCOUNT_RATE, df_capital_costs_skin.values.tolist())
|
||||
life_cycle_costs_capital_systems = _npv_from_list(DISCOUNT_RATE, df_capital_costs_systems.values.tolist())
|
||||
life_cycle_costs_end_of_life_costs = _npv_from_list(DISCOUNT_RATE, df_end_of_life_costs.values.tolist())
|
||||
life_cycle_operational_costs = _npv_from_list(DISCOUNT_RATE, df_operational_costs.values.tolist())
|
||||
life_cycle_maintenance_costs = _npv_from_list(DISCOUNT_RATE, df_maintenance_costs.values.tolist())
|
||||
life_cycle_operational_incomes = _npv_from_list(DISCOUNT_RATE, df_operational_incomes.values.tolist())
|
||||
life_cycle_capital_incomes = _npv_from_list(DISCOUNT_RATE, df_capital_incomes.values.tolist())
|
||||
|
||||
life_cycle_costs = (
|
||||
life_cycle_costs_capital_skin +
|
||||
life_cycle_costs_capital_systems +
|
||||
life_cycle_costs_end_of_life_costs +
|
||||
life_cycle_operational_costs +
|
||||
life_cycle_maintenance_costs -
|
||||
life_cycle_operational_incomes -
|
||||
life_cycle_capital_incomes
|
||||
)
|
||||
total_floor_area = lcc.calculate_total_floor_area()
|
||||
life_cycle_results[f'Scenario {retrofitting_scenario} building {building.name}'] = [life_cycle_costs_capital_skin,
|
||||
life_cycle_costs_capital_systems,
|
||||
life_cycle_costs_end_of_life_costs,
|
||||
life_cycle_operational_costs,
|
||||
life_cycle_maintenance_costs,
|
||||
-life_cycle_operational_incomes,
|
||||
-life_cycle_capital_incomes]
|
||||
|
||||
life_cycle_results.index = ['total_capital_costs_skin',
|
||||
'total_capital_costs_systems',
|
||||
'end_of_life_costs',
|
||||
'total_operational_costs',
|
||||
'total_maintenance_costs',
|
||||
'operational_incomes',
|
||||
'capital_incomes']
|
||||
|
||||
life_cycle_results = life_cycle_results.applymap(lambda x: round(x, 2))
|
||||
life_cycle_costs = round(life_cycle_costs, 2)
|
||||
list_pareto = [life_cycle_costs, valuepareto]
|
||||
Pareto[f' pareto scenario {retrofitting_scenario} building {building.name}'] = list_pareto
|
||||
Pareto1 = pd.DataFrame(list_pareto)
|
||||
total_floor_area_dataframe[f'building {building.name}']=[0]
|
||||
total_floor_area_dataframe.at[0,f'building {building.name}'] = total_floor_area
|
||||
# full_energy_path_output = Path(out_path_energy/'demand.csv'.resolve())
|
||||
# graphresults = printing_results()
|
||||
GlobalprintedLCC = printing_results(investmentcosts, life_cycle_results, total_floor_area, Pareto1,
|
||||
energy_outputs_for_graph, building.name)
|
||||
full_path_output = Path(out_path / f'TotalLCC_building{building.name}.xlsx').resolve()
|
||||
full_path_energy_output = Path(out_path / f'Consumption_building{building.name}.xlsx').resolve()
|
||||
with pd.ExcelWriter(full_path_output) as writer:
|
||||
GlobalprintedLCC.to_excel(writer, sheet_name=f'LCC_scenario{retrofitting_scenario}')
|
||||
total_floor_area_dataframe.to_excel(writer, sheet_name=f'Total areas{retrofitting_scenario}')
|
||||
with pd.ExcelWriter(full_path_energy_output) as writer:
|
||||
energy_outputs_for_graph.to_excel(writer, sheet_name=f'Final_energy_scenario{retrofitting_scenario}')
|
||||
total_floor_area_dataframe.to_excel(writer, sheet_name=f'Total areas{retrofitting_scenario}')
|
|
@ -8,7 +8,7 @@ from pathlib import Path
|
|||
# configurable parameters
|
||||
file_path = Path('./data/selected_building_2864.geojson').resolve()
|
||||
CONSTRUCTION_FORMAT = 'nrcan'
|
||||
USAGE_FORMAT = 'comnet'
|
||||
USAGE_FORMAT = 'nrcan'
|
||||
ENERGY_SYSTEM_FORMAT = 'montreal_custom'
|
||||
ATTIC_HEATED_CASE = 0
|
||||
BASEMENT_HEATED_CASE = 1
|
||||
|
|
|
@ -9,7 +9,7 @@ from pathlib import Path
|
|||
|
||||
import numpy_financial as npf
|
||||
import pandas as pd
|
||||
from hub.catalog_factories.costs_catalog_factory import CostCatalogFactory
|
||||
from hub.catalog_factories.costs_catalog_factory import CostsCatalogFactory
|
||||
from hub.helpers.dictionaries import Dictionaries
|
||||
from hub.imports.construction_factory import ConstructionFactory
|
||||
from hub.imports.energy_systems_factory import EnergySystemsFactory
|
||||
|
@ -19,229 +19,94 @@ from hub.imports.weather_factory import WeatherFactory
|
|||
from monthly_energy_balance_engine import MonthlyEnergyBalanceEngine
|
||||
from sra_engine import SraEngine
|
||||
from printing_results import *
|
||||
from Individualplot import *
|
||||
from hub.helpers import constants as cte
|
||||
from life_cycle_costs import LifeCycleCosts
|
||||
from LCC_calculation_scenarios import *
|
||||
|
||||
from costs import CONSTRUCTION_FORMAT
|
||||
from costs import ENERGY_SYSTEM_FORMAT, RETROFITTING_SCENARIOS, NUMBER_OF_YEARS
|
||||
from costs import CONSUMER_PRICE_INDEX, ELECTRICITY_PEAK_INDEX, ELECTRICITY_PRICE_INDEX, GAS_PRICE_INDEX, DISCOUNT_RATE
|
||||
from costs import SKIN_RETROFIT, SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV
|
||||
from costs import CURRENT_STATUS,SKIN_RETROFIT, SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV
|
||||
from costs import RETROFITTING_YEAR_CONSTRUCTION
|
||||
|
||||
# import paths
|
||||
from results import Results
|
||||
|
||||
|
||||
def _npv_from_list(npv_discount_rate, list_cashflow):
|
||||
lcc_value = npf.npv(npv_discount_rate, list_cashflow)
|
||||
return lcc_value
|
||||
|
||||
|
||||
def _search_archetype(costs_catalog, building_function):
|
||||
costs_archetypes = costs_catalog.entries('archetypes').archetypes
|
||||
for building_archetype in costs_archetypes:
|
||||
if str(building_function) == str(building_archetype.function):
|
||||
return building_archetype
|
||||
raise KeyError('archetype not found')
|
||||
|
||||
|
||||
life_cycle_results = pd.DataFrame()
|
||||
file_path = (Path(__file__).parent.parent / 'input_files' / 'summerschool_one_building.geojson')
|
||||
climate_reference_city = 'Montreal'
|
||||
file_path = (Path(__file__).parent.parent / 'input_files' / 'levis_v2.geojson')
|
||||
weather_format = 'epw'
|
||||
construction_format = 'nrcan'
|
||||
usage_format = 'nrcan'
|
||||
energy_systems_format = 'montreal_custom'
|
||||
attic_heated_case = 0
|
||||
basement_heated_case = 1
|
||||
|
||||
out_path = (Path(__file__).parent.parent / 'out_files')
|
||||
out_path_energy = (Path(__file__).parent.parent.parent / 'monthly_energy_balance_workflow' / 'output_files')
|
||||
tmp_folder = (Path(__file__).parent / 'tmp')
|
||||
|
||||
print('[simulation start]')
|
||||
city = GeometryFactory('geojson',
|
||||
city_original = GeometryFactory('geojson',
|
||||
path=file_path,
|
||||
height_field='citygml_me',
|
||||
year_of_construction_field='ANNEE_CONS',
|
||||
function_field='CODE_UTILI',
|
||||
function_to_hub=Dictionaries().montreal_function_to_hub_function).city
|
||||
city.climate_reference_city = climate_reference_city
|
||||
city.climate_file = (tmp_folder / f'{climate_reference_city}.cli').resolve()
|
||||
|
||||
print(f'city created from {file_path}')
|
||||
WeatherFactory(weather_format, city).enrich()
|
||||
print('enrich weather... done')
|
||||
ConstructionFactory(construction_format, city).enrich()
|
||||
ConstructionFactory(construction_format, city_original).enrich()
|
||||
print('enrich constructions... done')
|
||||
UsageFactory(usage_format, city).enrich()
|
||||
UsageFactory(usage_format, city_original).enrich()
|
||||
print('enrich usage... done')
|
||||
for building in city.buildings:
|
||||
building.energy_systems_archetype_name = 'system 1 gas pv'
|
||||
EnergySystemsFactory(energy_systems_format, city).enrich()
|
||||
for building in city_original.buildings:
|
||||
building.energy_systems_archetype_name = 'system 1 gas'
|
||||
EnergySystemsFactory(energy_systems_format, city_original).enrich()
|
||||
print('enrich systems... done')
|
||||
|
||||
print('exporting:')
|
||||
sra_file = (tmp_folder / f'{city.name}_sra.xml').resolve()
|
||||
SraEngine(city, sra_file, tmp_folder)
|
||||
sra_file = (tmp_folder / f'{city_original.name}_sra.xml').resolve()
|
||||
SraEngine(city_original, sra_file, tmp_folder)
|
||||
print(' sra processed...')
|
||||
catalog = CostCatalogFactory('montreal_custom').catalog
|
||||
catalog = CostsCatalogFactory('montreal_custom').catalog
|
||||
city = city_original.copy
|
||||
total_floor_area = 0
|
||||
|
||||
for retrofitting_scenario in RETROFITTING_SCENARIOS:
|
||||
retrofitting_scenario = SYSTEM_RETROFIT_AND_PV
|
||||
|
||||
if retrofitting_scenario in (SKIN_RETROFIT, SYSTEM_RETROFIT_AND_PV):
|
||||
if retrofitting_scenario == SYSTEM_RETROFIT_AND_PV:
|
||||
print(f'retrofitting 1')
|
||||
for building in city.buildings:
|
||||
building.energy_systems_archetype_name = 'system 7 electricity pv'
|
||||
EnergySystemsFactory(ENERGY_SYSTEM_FORMAT, city).enrich()
|
||||
|
||||
if retrofitting_scenario == SKIN_RETROFIT:
|
||||
for building in city.buildings:
|
||||
building.year_of_construction = RETROFITTING_YEAR_CONSTRUCTION
|
||||
ConstructionFactory(CONSTRUCTION_FORMAT, city).enrich()
|
||||
print('enrich retrofitted constructions... done')
|
||||
building.energy_systems_archetype_name = 'system 1 gas'
|
||||
ConstructionFactory(construction_format, city).enrich()
|
||||
print(f'retrofitting 2')
|
||||
|
||||
if retrofitting_scenario in (SYSTEM_RETROFIT_AND_PV, SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV):
|
||||
if retrofitting_scenario == SKIN_RETROFIT_AND_SYSTEM_RETROFIT_AND_PV:
|
||||
for building in city.buildings:
|
||||
building.energy_systems_archetype_name = 'system 6 electricity pv'
|
||||
building.year_of_construction = RETROFITTING_YEAR_CONSTRUCTION
|
||||
building.energy_systems_archetype_name = 'system 7 electricity pv'
|
||||
ConstructionFactory(construction_format, city).enrich()
|
||||
EnergySystemsFactory(ENERGY_SYSTEM_FORMAT, city).enrich()
|
||||
print('enrich systems... done')
|
||||
print(f'retrofitting 3')
|
||||
|
||||
MonthlyEnergyBalanceEngine(city, tmp_folder)
|
||||
print(' insel processed...')
|
||||
else:
|
||||
print('running base case')
|
||||
|
||||
for building in city.buildings:
|
||||
for energy_system in building.energy_systems:
|
||||
if cte.HEATING in energy_system.demand_types:
|
||||
energy_system.generation_system.heat_power = building.heating_peak_load[cte.YEAR][0]
|
||||
if cte.COOLING in energy_system.demand_types:
|
||||
energy_system.generation_system.cooling_power = building.cooling_peak_load[cte.YEAR][0]
|
||||
print(f' heating consumption {building.heating_consumption[cte.YEAR][0]}')
|
||||
print('importing results:')
|
||||
results = Results(city, out_path)
|
||||
results.print()
|
||||
print('results printed...')
|
||||
MonthlyEnergyBalanceEngine(city, tmp_folder)
|
||||
print(' insel processed...')
|
||||
results = Results(city, out_path)
|
||||
results.print()
|
||||
energy_outputs_for_graph = pd.DataFrame()
|
||||
energy_outputs_for_graph, valuepareto = \
|
||||
results.outputsforgraph()
|
||||
energy_outputs_for_graph = energy_outputs_for_graph/1000
|
||||
print('results printed...')
|
||||
|
||||
print('[simulation end]')
|
||||
LCC_calculation_scenarios(city, catalog, retrofitting_scenario, valuepareto, out_path, energy_outputs_for_graph)
|
||||
|
||||
print(f'beginning costing scenario {retrofitting_scenario} systems... done')
|
||||
|
||||
for building in city.buildings:
|
||||
total_floor_area = 0
|
||||
function = Dictionaries().hub_function_to_montreal_custom_costs_function[building.function]
|
||||
archetype = _search_archetype(catalog, function)
|
||||
print('lcc for first building started')
|
||||
if "gas" in building.energy_systems_archetype_name:
|
||||
FUEL_TYPE = 1
|
||||
else:
|
||||
FUEL_TYPE = 0
|
||||
|
||||
lcc = LifeCycleCosts(building, archetype, NUMBER_OF_YEARS, CONSUMER_PRICE_INDEX, ELECTRICITY_PEAK_INDEX,
|
||||
ELECTRICITY_PRICE_INDEX, GAS_PRICE_INDEX, DISCOUNT_RATE, retrofitting_scenario, FUEL_TYPE)
|
||||
global_capital_costs, global_capital_incomes = lcc.calculate_capital_costs()
|
||||
global_end_of_life_costs = lcc.calculate_end_of_life_costs()
|
||||
global_operational_costs = lcc.calculate_total_operational_costs
|
||||
global_maintenance_costs = lcc.calculate_total_maintenance_costs()
|
||||
global_operational_incomes = lcc.calculate_total_operational_incomes(retrofitting_scenario)
|
||||
full_path_output = Path(out_path / f'output {retrofitting_scenario} {building.name}.xlsx').resolve()
|
||||
with pd.ExcelWriter(full_path_output) as writer:
|
||||
global_capital_costs.to_excel(writer, sheet_name='global_capital_costs')
|
||||
global_end_of_life_costs.to_excel(writer, sheet_name='global_end_of_life_costs')
|
||||
global_operational_costs.to_excel(writer, sheet_name='global_operational_costs')
|
||||
global_maintenance_costs.to_excel(writer, sheet_name='global_maintenance_costs')
|
||||
global_operational_incomes.to_excel(writer, sheet_name='global_operational_incomes')
|
||||
global_capital_incomes.to_excel(writer, sheet_name='global_capital_incomes')
|
||||
|
||||
investmentcosts = pd.DataFrame([])
|
||||
print('RETROFITTING SCENARIO', retrofitting_scenario)
|
||||
if retrofitting_scenario == 0:
|
||||
investmentcosts = [global_capital_costs['B2010_opaque_walls'][0],
|
||||
global_capital_costs['B2020_transparent'][0],
|
||||
global_capital_costs['B3010_opaque_roof'][0],
|
||||
global_capital_costs['B10_superstructure'][0],
|
||||
global_capital_costs['D3020_heat_generating_systems'][0],
|
||||
global_capital_costs['D3080_other_hvac_ahu'][0],
|
||||
global_capital_costs['D5020_lighting_and_branch_wiring'][0],
|
||||
global_capital_costs['D301010_photovoltaic_system'][0]]
|
||||
investmentcosts = pd.DataFrame(investmentcosts)
|
||||
|
||||
else:
|
||||
investmentcosts[f'retrofitting_scenario_{retrofitting_scenario}'] = \
|
||||
[global_capital_costs['B2010_opaque_walls'][0],
|
||||
global_capital_costs['B2020_transparent'][0],
|
||||
global_capital_costs['B3010_opaque_roof'][0],
|
||||
global_capital_costs['B10_superstructure'][0],
|
||||
global_capital_costs['D3020_heat_generating_systems'][0],
|
||||
global_capital_costs['D3080_other_hvac_ahu'][0],
|
||||
global_capital_costs['D5020_lighting_and_branch_wiring'][0],
|
||||
global_capital_costs['D301010_photovoltaic_system'][0]]
|
||||
|
||||
investmentcosts.index = ['Opaque walls', 'Transparent walls', 'Opaque roof', 'Superstructure',
|
||||
'Heat generation systems', 'Other HVAC AHU', 'Lighting and branch wiring', 'PV systems']
|
||||
|
||||
df_capital_costs_skin = (
|
||||
global_capital_costs['B2010_opaque_walls'] + global_capital_costs['B2020_transparent'] +
|
||||
global_capital_costs['B3010_opaque_roof'] + global_capital_costs['B10_superstructure']
|
||||
)
|
||||
df_capital_costs_systems = (
|
||||
global_capital_costs['D3020_heat_generating_systems'] +
|
||||
global_capital_costs['D3030_cooling_generation_systems'] +
|
||||
global_capital_costs['D3080_other_hvac_ahu'] +
|
||||
global_capital_costs['D5020_lighting_and_branch_wiring'] +
|
||||
global_capital_costs['D301010_photovoltaic_system']
|
||||
)
|
||||
df_end_of_life_costs = global_end_of_life_costs['End_of_life_costs']
|
||||
df_operational_costs = (
|
||||
global_operational_costs['Fixed_costs_electricity_peak'] +
|
||||
global_operational_costs['Fixed_costs_electricity_monthly'] +
|
||||
global_operational_costs['Fixed_costs_electricity_peak'] +
|
||||
global_operational_costs['Fixed_costs_electricity_monthly'] +
|
||||
global_operational_costs['Variable_costs_electricity'] +
|
||||
global_operational_costs['Fixed_costs_gas'] +
|
||||
global_operational_costs['Variable_costs_gas']
|
||||
)
|
||||
df_maintenance_costs = (
|
||||
global_maintenance_costs['Heating_maintenance'] +
|
||||
global_maintenance_costs['Cooling_maintenance'] +
|
||||
global_maintenance_costs['PV_maintenance']
|
||||
)
|
||||
df_operational_incomes = global_operational_incomes['Incomes electricity']
|
||||
|
||||
df_capital_incomes = (
|
||||
global_capital_incomes['Subsidies construction'] +
|
||||
global_capital_incomes['Subsidies HVAC'] +
|
||||
global_capital_incomes['Subsidies PV']
|
||||
)
|
||||
|
||||
life_cycle_costs_capital_skin = _npv_from_list(DISCOUNT_RATE, df_capital_costs_skin.values.tolist())
|
||||
life_cycle_costs_capital_systems = _npv_from_list(DISCOUNT_RATE, df_capital_costs_systems.values.tolist())
|
||||
life_cycle_costs_end_of_life_costs = _npv_from_list(DISCOUNT_RATE, df_end_of_life_costs.values.tolist())
|
||||
life_cycle_operational_costs = _npv_from_list(DISCOUNT_RATE, df_operational_costs.values.tolist())
|
||||
life_cycle_maintenance_costs = _npv_from_list(DISCOUNT_RATE, df_maintenance_costs.values.tolist())
|
||||
life_cycle_operational_incomes = _npv_from_list(DISCOUNT_RATE, df_operational_incomes.values.tolist())
|
||||
life_cycle_capital_incomes = _npv_from_list(DISCOUNT_RATE, df_capital_incomes.values.tolist())
|
||||
|
||||
life_cycle_costs = (
|
||||
life_cycle_costs_capital_skin +
|
||||
life_cycle_costs_capital_systems +
|
||||
life_cycle_costs_end_of_life_costs +
|
||||
life_cycle_operational_costs +
|
||||
life_cycle_maintenance_costs -
|
||||
life_cycle_operational_incomes -
|
||||
life_cycle_capital_incomes
|
||||
)
|
||||
total_floor_area += lcc.calculate_total_floor_area()
|
||||
life_cycle_results[f'Scenario {retrofitting_scenario}'] = [life_cycle_costs_capital_skin,
|
||||
life_cycle_costs_capital_systems,
|
||||
life_cycle_costs_end_of_life_costs,
|
||||
life_cycle_operational_costs,
|
||||
life_cycle_maintenance_costs,
|
||||
-life_cycle_operational_incomes,
|
||||
-life_cycle_capital_incomes]
|
||||
|
||||
life_cycle_results.index = ['total_capital_costs_skin',
|
||||
'total_capital_costs_systems',
|
||||
'end_of_life_costs',
|
||||
'total_operational_costs',
|
||||
'total_maintenance_costs',
|
||||
'operational_incomes',
|
||||
'capital_incomes']
|
||||
|
||||
print(f'Scenario {retrofitting_scenario} {life_cycle_costs}')
|
||||
|
||||
# printing_results(investmentcosts, life_cycle_results, total_floor_area)
|
||||
print("RUN SUCCESSFUL!")
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ class LifeCycleCosts:
|
|||
roof_area = 0
|
||||
for roof in building.roofs:
|
||||
roof_area += roof.solid_polygon.area
|
||||
surface_pv = roof_area * 0.5
|
||||
surface_pv = roof_area * 0.2
|
||||
|
||||
self._yearly_capital_costs.loc[0, 'B2010_opaque_walls'] = 0
|
||||
self._yearly_capital_costs.loc[0]['B2020_transparent'] = 0
|
||||
|
@ -156,11 +156,15 @@ class LifeCycleCosts:
|
|||
capital_cost_other_hvac_ahu = peak_cooling * chapter.item('D3080_other_hvac_ahu').initial_investment[0]
|
||||
capital_cost_lighting = total_floor_area * chapter.item('D5020_lighting_and_branch_wiring').initial_investment[0]
|
||||
|
||||
self._yearly_capital_costs.loc[0, 'D3020_heat_generating_systems'] = capital_cost_heating_equipment * (1-PERCENTAGE_CREDIT)
|
||||
self._yearly_capital_costs.loc[0, 'D3030_cooling_generation_systems'] = capital_cost_cooling_equipment * (1-PERCENTAGE_CREDIT)
|
||||
self._yearly_capital_costs.loc[0, 'D3040_distribution_systems'] = capital_cost_distribution_equipment * (1-PERCENTAGE_CREDIT)
|
||||
self._yearly_capital_costs.loc[0, 'D3020_heat_generating_systems'] = capital_cost_heating_equipment * \
|
||||
(1-PERCENTAGE_CREDIT)
|
||||
self._yearly_capital_costs.loc[0, 'D3030_cooling_generation_systems'] = capital_cost_cooling_equipment * \
|
||||
(1-PERCENTAGE_CREDIT)
|
||||
self._yearly_capital_costs.loc[0, 'D3040_distribution_systems'] = capital_cost_distribution_equipment * \
|
||||
(1-PERCENTAGE_CREDIT)
|
||||
self._yearly_capital_costs.loc[0, 'D3080_other_hvac_ahu'] = capital_cost_other_hvac_ahu * (1-PERCENTAGE_CREDIT)
|
||||
self._yearly_capital_costs.loc[0, 'D5020_lighting_and_branch_wiring'] = capital_cost_lighting * (1-PERCENTAGE_CREDIT)
|
||||
self._yearly_capital_costs.loc[0, 'D5020_lighting_and_branch_wiring'] = capital_cost_lighting * \
|
||||
(1-PERCENTAGE_CREDIT)
|
||||
|
||||
for year in range(1, self._number_of_years):
|
||||
chapter = chapters.chapter('D_services')
|
||||
|
@ -219,7 +223,8 @@ class LifeCycleCosts:
|
|||
capital_cost_heating_equipment +
|
||||
capital_cost_cooling_equipment +
|
||||
capital_cost_distribution_equipment +
|
||||
capital_cost_other_hvac_ahu + capital_cost_lighting
|
||||
capital_cost_other_hvac_ahu +
|
||||
capital_cost_lighting
|
||||
)
|
||||
|
||||
self._yearly_capital_incomes.loc[0, 'Subsidies construction'] = (
|
||||
|
@ -249,7 +254,7 @@ class LifeCycleCosts:
|
|||
def calculate_total_floor_area(self):
|
||||
total_floor_area = self._total_floor_area
|
||||
return total_floor_area
|
||||
@property
|
||||
|
||||
def calculate_total_operational_costs(self):
|
||||
"""
|
||||
Calculate total operational costs
|
||||
|
@ -270,8 +275,9 @@ class LifeCycleCosts:
|
|||
(building.heating_consumption[cte.YEAR][0] + building.domestic_hot_water_consumption[cte.YEAR][0]) / 1000 *
|
||||
archetype.operational_cost.fuels[1].variable[0]
|
||||
)
|
||||
if self._fuel_type == 0:
|
||||
electricity_heating = building.heating_consumption[cte.YEAR][0] / 1000
|
||||
else:
|
||||
# todo: change hardcoded 3 to include COP heating system
|
||||
electricity_heating = building.heating_consumption[cte.YEAR][0] /(1000)
|
||||
domestic_hot_water_electricity = building.domestic_hot_water_consumption[cte.YEAR][0] / 1000
|
||||
|
||||
electricity_cooling = building.cooling_consumption[cte.YEAR][0] / 1000
|
||||
|
@ -282,14 +288,12 @@ class LifeCycleCosts:
|
|||
electricity_heating + electricity_cooling + electricity_lighting + domestic_hot_water_electricity +
|
||||
electricity_plug_loads + electricity_distribution
|
||||
)
|
||||
print(f'electricity consumption {total_electricity_consumption}')
|
||||
|
||||
# todo: change when peak electricity demand is coded. Careful with factor residential
|
||||
peak_electricity_demand = 0.1*total_floor_area # self._peak_electricity_demand
|
||||
variable_electricity_cost_year_0 = total_electricity_consumption * archetype.operational_cost.fuels[0].variable[0]
|
||||
peak_electricity_cost_year_0 = peak_electricity_demand * archetype.operational_cost.fuels[0].fixed_power * 12
|
||||
monthly_electricity_cost_year_0 = archetype.operational_cost.fuels[0].fixed_monthly * 12 * factor_residential
|
||||
|
||||
variable_electricity_cost_year_0 = total_electricity_consumption * archetype.operational_cost.fuels[0].variable[0]
|
||||
for year in range(1, self._number_of_years + 1):
|
||||
price_increase_electricity = math.pow(1 + self._electricity_price_index, year)
|
||||
price_increase_peak_electricity = math.pow(1 + self._electricity_peak_index, year)
|
||||
|
@ -315,7 +319,7 @@ class LifeCycleCosts:
|
|||
|
||||
return self._yearly_operational_costs
|
||||
|
||||
def calculate_total_operational_incomes(self, retrofitting_scenario):
|
||||
def calculate_total_operational_incomes(self):
|
||||
"""
|
||||
Calculate total operational incomes
|
||||
:return: pd.DataFrame
|
||||
|
@ -323,16 +327,13 @@ class LifeCycleCosts:
|
|||
building = self._building
|
||||
if cte.YEAR not in building.onsite_electrical_production:
|
||||
onsite_electricity_production = 0
|
||||
else:
|
||||
if retrofitting_scenario == 0 or retrofitting_scenario == 1:
|
||||
onsite_electricity_production = 0
|
||||
else:
|
||||
onsite_electricity_production = building.onsite_electrical_production[cte.YEAR][0]/1000
|
||||
|
||||
for year in range(1, self._number_of_years + 1):
|
||||
price_increase_electricity = math.pow(1 + self._electricity_price_index, year)
|
||||
# todo: check the adequate assignation of price. Pilar
|
||||
price_export = 0.075 # archetype.income.electricity_export
|
||||
price_export = self._archetype.income.electricity_export*3600000
|
||||
self._yearly_operational_incomes.loc[year, 'Incomes electricity'] = (
|
||||
onsite_electricity_production * price_export * price_increase_electricity
|
||||
)
|
||||
|
@ -353,11 +354,11 @@ class LifeCycleCosts:
|
|||
roof_area += roof.solid_polygon.area
|
||||
surface_pv = roof_area * 0.5
|
||||
|
||||
peak_heating = building.heating_peak_load[cte.YEAR][0]/1000
|
||||
peak_cooling = building.heating_peak_load[cte.YEAR][0]/1000
|
||||
|
||||
maintenance_heating_0 = peak_heating * archetype.operational_cost.maintenance_heating
|
||||
maintenance_cooling_0 = peak_cooling * archetype.operational_cost.maintenance_cooling
|
||||
peak_heating = building.heating_peak_load[cte.YEAR][0]
|
||||
peak_cooling = building.heating_peak_load[cte.YEAR][0]
|
||||
#todo: check the values for maintenance
|
||||
maintenance_heating_0 = peak_heating * archetype.operational_cost.maintenance_heating*0.5
|
||||
maintenance_cooling_0 = peak_cooling * archetype.operational_cost.maintenance_cooling*0.5
|
||||
maintenance_pv_0 = surface_pv * archetype.operational_cost.maintenance_pv
|
||||
|
||||
for year in range(1, self._number_of_years + 1):
|
||||
|
|
|
@ -1,58 +1,69 @@
|
|||
import plotly.graph_objects as go
|
||||
import matplotlib.pyplot as plt
|
||||
import plotly.express as px
|
||||
|
||||
|
||||
def printing_results(investmentcosts, life_cycle_results,total_floor_area):
|
||||
|
||||
labels = investmentcosts.index
|
||||
values = investmentcosts['retrofitting_scenario_1']
|
||||
values2 = investmentcosts['retrofitting_scenario_2']
|
||||
values3 = investmentcosts['retrofitting_scenario_3']
|
||||
|
||||
fig = go.Figure(data=[go.Pie(labels=labels, values=values)])
|
||||
fig2 = go.Figure(data=[go.Pie(labels=labels, values=values2)])
|
||||
fig3 = go.Figure(data=[go.Pie(labels=labels, values=values3)])
|
||||
# Set the layout properties
|
||||
fig.update_layout(
|
||||
title='Retrofitting scenario 1',
|
||||
showlegend=True
|
||||
)
|
||||
fig2.update_layout(
|
||||
title='Retrofitting scenario 2',
|
||||
showlegend=True
|
||||
)
|
||||
fig3.update_layout(
|
||||
title='Retrofitting scenario 3',
|
||||
showlegend=True
|
||||
def printing_results(investmentcosts, life_cycle_results,total_floor_area, Pareto,energy_outputs_for_graph,
|
||||
building_name):
|
||||
# Normalized investment costs
|
||||
investmentcosts_swapped = investmentcosts.transpose()
|
||||
investmentcosts_swapped = round(investmentcosts_swapped, 2)
|
||||
trace1 = go.Bar(x=investmentcosts_swapped.index, y=investmentcosts_swapped['Opaque walls'], name='Opaque walls')
|
||||
trace2 = go.Bar(x=investmentcosts_swapped.index, y=investmentcosts_swapped['Transparent walls'],
|
||||
name='Transparent walls')
|
||||
trace3 = go.Bar(x=investmentcosts_swapped.index, y=investmentcosts_swapped['Opaque roof'], name='Opaque roof')
|
||||
trace4 = go.Bar(x=investmentcosts_swapped.index, y=investmentcosts_swapped['Superstructure'], name='Superstructure')
|
||||
trace5 = go.Bar(x=investmentcosts_swapped.index, y=investmentcosts_swapped['Heat generation systems'],
|
||||
name='Heat generation systems')
|
||||
trace6 = go.Bar(x=investmentcosts_swapped.index, y=investmentcosts_swapped['Other HVAC AHU'], name='Other HVAC AHU')
|
||||
trace7 = go.Bar(x=investmentcosts_swapped.index, y=investmentcosts_swapped['Lighting and branch wiring'],
|
||||
name='Lighting and branch wiring')
|
||||
trace8 = go.Bar(x=investmentcosts_swapped.index, y=investmentcosts_swapped['PV systems'], name='PV systems')
|
||||
data = [trace1, trace2,trace3,trace4,trace5,trace6,trace7,trace8]
|
||||
layout = go.Layout(
|
||||
title=f'Investment costs scenarios for building {building_name}',
|
||||
xaxis=dict(title='Scenarios'),
|
||||
yaxis=dict(title='Investment costs (CAD)'),
|
||||
barmode='stack'
|
||||
)
|
||||
figinvestment = go.Figure(data=data, layout=layout)
|
||||
|
||||
# Display the chart
|
||||
fig.show()
|
||||
fig2.show()
|
||||
fig3.show()
|
||||
|
||||
df = life_cycle_results / total_floor_area
|
||||
|
||||
# Transpose the DataFrame (swap columns and rows)
|
||||
#Life cycle costs graph
|
||||
df = life_cycle_results
|
||||
df_swapped = df.transpose()
|
||||
|
||||
# Reset the index to make the current index a regular column
|
||||
df_swapped = df_swapped.reset_index()
|
||||
|
||||
# Assign new column names
|
||||
df_swapped.columns = ['Scenarios', 'total_capital_costs_skin',
|
||||
df_swapped.columns = ['Scenarios','total_capital_costs_skin',
|
||||
'total_capital_costs_systems',
|
||||
'end_of_life_costs',
|
||||
'total_operational_costs',
|
||||
'total_maintenance_costs',
|
||||
'operational_incomes',
|
||||
'capital_incomes']
|
||||
|
||||
df_swapped.index = df_swapped['Scenarios']
|
||||
df_swapped = df_swapped.drop('Scenarios', axis=1)
|
||||
print(df_swapped)
|
||||
fig = px.bar(df_swapped, title='Life Cycle Costs for buildings')
|
||||
df_swapped = round(df_swapped,2)
|
||||
fig = px.bar(df_swapped, title=f'Life Cycle Costs for building {building_name}')
|
||||
|
||||
#Pareto graph
|
||||
Paretoswapped = Pareto.transpose() / total_floor_area
|
||||
Paretoswapped = Paretoswapped.applymap(lambda x: round(x, 2))
|
||||
Paretoswapped.columns = ['Life Cycle Costs', 'Value pareto']
|
||||
fig_pareto = px.scatter(x=Paretoswapped['Value pareto'], y=Paretoswapped['Life Cycle Costs'])
|
||||
# Add labels and title
|
||||
fig_pareto.update_layout(
|
||||
xaxis_title='Yearly specific final energy consumption (kWh/m2) ',
|
||||
yaxis_title='Specific Life Cycle Costs (kWh/m2)',
|
||||
title=f'Combination of LCC and energy in building {building_name}'
|
||||
)
|
||||
#Pie chart
|
||||
normalized_outputs = round(energy_outputs_for_graph/(total_floor_area),2)
|
||||
figpie = px.pie(normalized_outputs, values=normalized_outputs[f'building {building_name}'],
|
||||
names=normalized_outputs.index, title=f'Energy distribution in building {building_name}')
|
||||
|
||||
# Display the plot
|
||||
fig.show()
|
||||
# Display the chart
|
||||
plt.show()
|
||||
figinvestment.show()
|
||||
fig_pareto.show()
|
||||
figpie.show()
|
||||
|
||||
return df_swapped
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user