Compare commits
No commits in common. "4ad60765dfea50a1ff35484cca9c1902db5d1fc4" and "5ec1b33bdca9e476f68782ec60907de875eeda03" have entirely different histories.
4ad60765df
...
5ec1b33bdc
@ -1,209 +0,0 @@
|
|||||||
import pandas as pd
|
|
||||||
import numpy as np
|
|
||||||
import hub.helpers.constants as cte
|
|
||||||
from hub.exports.energy_building_exports_factory import EnergyBuildingsExportsFactory
|
|
||||||
from hub.imports.geometry_factory import GeometryFactory
|
|
||||||
from hub.imports.results_factory import ResultFactory
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inflation_rate = 0.03
|
|
||||||
discount_rate = 0.05
|
|
||||||
period = 25
|
|
||||||
installation_cost = 0
|
|
||||||
tax_deduct= 0
|
|
||||||
incentive= 0
|
|
||||||
capacity =30
|
|
||||||
degradation_rate = 0.01
|
|
||||||
year_of_replacement_list= [12]
|
|
||||||
replacement_ratio = 0.1
|
|
||||||
maintenance_cost_ratio =0.01
|
|
||||||
dataframe_path= r'C:\Users\z_keshav\CMM_PV\data\test.csv'
|
|
||||||
Building_function = "residential"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_pv_system_metrics(
|
|
||||||
dataframe_path, # input from Hub
|
|
||||||
Building_function, # input from Hub
|
|
||||||
inflation_rate,
|
|
||||||
discount_rate,
|
|
||||||
period,
|
|
||||||
capacity, # input from Hub
|
|
||||||
degradation_rate,
|
|
||||||
year_of_replacement_list,
|
|
||||||
replacement_ratio,
|
|
||||||
maintenance_cost_ratio,
|
|
||||||
installation_cost=0,
|
|
||||||
tax_deduct=0,
|
|
||||||
incentive=0,
|
|
||||||
):
|
|
||||||
# Read the data
|
|
||||||
dataframe = pd.read_csv(dataframe_path)
|
|
||||||
building_hourly_consumption = dataframe['GRID_kWh'] # input from Hub
|
|
||||||
PV_hourly_generation = dataframe['PV_roofs_top_E_kWh'] # input from Hub
|
|
||||||
|
|
||||||
# Defining tariff based on building function
|
|
||||||
if Building_function == "residential": # Rate D when the maximum power demand has reached 50 kW or more
|
|
||||||
grid_current_tariff = 0.06704 # Residential tariff in $/kWh
|
|
||||||
elif Building_function == "commercial": # Rate G: General rate for small-power customers with demand ≤ 50 kW
|
|
||||||
grid_current_tariff = 0.11518 # Commercial tariff in $/kWh
|
|
||||||
|
|
||||||
# Initial Calculations for Year 1
|
|
||||||
first_year_generation_PV = PV_hourly_generation.sum()
|
|
||||||
first_year_self_consumption = np.minimum(PV_hourly_generation, building_hourly_consumption).sum()
|
|
||||||
first_year_grid_purchase = np.maximum(building_hourly_consumption - PV_hourly_generation, 0).sum()
|
|
||||||
first_year_PV_export = np.maximum(PV_hourly_generation - building_hourly_consumption, 0).sum()
|
|
||||||
|
|
||||||
# Cost per kW determination
|
|
||||||
if capacity <= 2.5:
|
|
||||||
cost_per_kW = 4000
|
|
||||||
elif 2.5 < capacity <= 5:
|
|
||||||
cost_per_kW = 3000
|
|
||||||
elif 5 < capacity <= 10:
|
|
||||||
cost_per_kW = 2500
|
|
||||||
elif 10 < capacity <= 15:
|
|
||||||
cost_per_kW = 2300
|
|
||||||
elif 15 < capacity <= 20:
|
|
||||||
cost_per_kW = 2000
|
|
||||||
elif 20 < capacity <= 10000:
|
|
||||||
cost_per_kW = 1800
|
|
||||||
else:
|
|
||||||
cost_per_kW = 1449
|
|
||||||
|
|
||||||
|
|
||||||
# Initial costs
|
|
||||||
initial_cost = capacity * cost_per_kW
|
|
||||||
|
|
||||||
# Discounted metrics initialization
|
|
||||||
discounted_generation_per_year = {}
|
|
||||||
discounted_self_consumption_per_year = {}
|
|
||||||
discounted_building_export_per_year = {}
|
|
||||||
discounted_grid_purchase_per_year = {}
|
|
||||||
discounted_total_generation = 0
|
|
||||||
discounted_total_self_consumption = 0
|
|
||||||
discounted_total_building_export = 0
|
|
||||||
discounted_total_grid_purchase = 0
|
|
||||||
discounted_annual_cost = {}
|
|
||||||
discounted_total_cost = 0
|
|
||||||
discounted_income_per_year = {}
|
|
||||||
total_discounted_income = 0
|
|
||||||
total_discounted_net_metering_income = 0
|
|
||||||
|
|
||||||
# Replacement costs calculation
|
|
||||||
replacement_cost = {
|
|
||||||
year: capacity * cost_per_kW * replacement_ratio * ((1 + inflation_rate) ** year) / (
|
|
||||||
(1 + discount_rate) ** year)
|
|
||||||
for year in year_of_replacement_list
|
|
||||||
}
|
|
||||||
|
|
||||||
# Yearly calculations
|
|
||||||
for year in range(1, period + 1):
|
|
||||||
# Apply degradation to PV generation for the current year
|
|
||||||
PV_hourly_generation_degraded = PV_hourly_generation * ((1 - degradation_rate) ** (year - 1))
|
|
||||||
|
|
||||||
# Hourly self-consumption and export considering degraded generation
|
|
||||||
building_hourly_self_consumption = np.minimum(PV_hourly_generation_degraded, building_hourly_consumption)
|
|
||||||
building_hourly_export = np.maximum(PV_hourly_generation_degraded - building_hourly_consumption, 0)
|
|
||||||
building_hourly_grid_purchase = np.maximum(building_hourly_consumption - PV_hourly_generation_degraded, 0).sum()
|
|
||||||
|
|
||||||
# Annual values
|
|
||||||
annual_self_consumption = building_hourly_self_consumption.sum()
|
|
||||||
annual_generation = PV_hourly_generation_degraded.sum()
|
|
||||||
annual_PV_export = building_hourly_export.sum()
|
|
||||||
annual_grid_purchase = building_hourly_grid_purchase.sum()
|
|
||||||
|
|
||||||
# Discounted values
|
|
||||||
discounted_generation = annual_generation / ((1 + discount_rate) ** year)
|
|
||||||
discounted_self_consumption = annual_self_consumption / ((1 + discount_rate) ** year)
|
|
||||||
discounted_building_export = annual_PV_export / ((1 + discount_rate) ** year)
|
|
||||||
discounted_grid_purchase = annual_grid_purchase / ((1 + discount_rate) ** year)
|
|
||||||
|
|
||||||
# Add to total discounted values
|
|
||||||
discounted_generation_per_year[year] = discounted_generation
|
|
||||||
discounted_self_consumption_per_year[year] = discounted_self_consumption
|
|
||||||
discounted_building_export_per_year[year] = discounted_building_export
|
|
||||||
discounted_grid_purchase_per_year[year] = discounted_grid_purchase
|
|
||||||
|
|
||||||
# Calculate total values in Life Cycle
|
|
||||||
discounted_total_generation += discounted_generation
|
|
||||||
discounted_total_self_consumption += discounted_self_consumption
|
|
||||||
discounted_total_building_export += discounted_building_export
|
|
||||||
discounted_total_grid_purchase += discounted_grid_purchase
|
|
||||||
|
|
||||||
# Annual costs
|
|
||||||
annual_opex = initial_cost * maintenance_cost_ratio * ((1 + inflation_rate) ** year) / (
|
|
||||||
(1 + discount_rate) ** year)
|
|
||||||
annual_cost = (
|
|
||||||
initial_cost if year == 1
|
|
||||||
else annual_opex + replacement_cost.get(year, 0)
|
|
||||||
)
|
|
||||||
discounted_annual_cost[year] = annual_cost
|
|
||||||
discounted_total_cost += annual_cost
|
|
||||||
|
|
||||||
# Tariff adjustment for income
|
|
||||||
inflated_grid_tariff = grid_current_tariff * ((1 + inflation_rate) ** (year - 1))
|
|
||||||
discounted_factor = ((1 + discount_rate) ** year) ** -1
|
|
||||||
|
|
||||||
# Income from self-consumption and net metering
|
|
||||||
self_consumption_income = discounted_self_consumption * inflated_grid_tariff
|
|
||||||
net_metering_income = min(annual_PV_export, first_year_grid_purchase) * inflated_grid_tariff * discounted_factor
|
|
||||||
tax_deduction_income = (
|
|
||||||
initial_cost * (1 + tax_deduct) * ((1 - tax_deduct) ** (year - 1)) * tax_deduct
|
|
||||||
)
|
|
||||||
|
|
||||||
annual_income = self_consumption_income + net_metering_income + tax_deduction_income
|
|
||||||
discounted_income_per_year[year] = annual_income
|
|
||||||
total_discounted_income += annual_income
|
|
||||||
total_discounted_net_metering_income += net_metering_income
|
|
||||||
|
|
||||||
total_discounted_income += incentive
|
|
||||||
|
|
||||||
# LCOE calculations
|
|
||||||
if discounted_total_generation == 0:
|
|
||||||
raise ValueError("Discounted generation is zero, cannot calculate LCOE.")
|
|
||||||
|
|
||||||
# To compute the LCOE for exported energy accurately,
|
|
||||||
# you should isolate the portion of the discounted income that comes only from energy exported to the grid,
|
|
||||||
# over the total discounted exported energy
|
|
||||||
# Loec of purchasing from grid is same as tariff
|
|
||||||
|
|
||||||
lcoe_pv = discounted_total_cost / discounted_total_generation
|
|
||||||
|
|
||||||
total_transaction = (
|
|
||||||
discounted_total_self_consumption +
|
|
||||||
discounted_total_building_export +
|
|
||||||
discounted_total_grid_purchase
|
|
||||||
)
|
|
||||||
|
|
||||||
# lcoe of exported electricity for net metering
|
|
||||||
lcoe_export = (
|
|
||||||
total_discounted_net_metering_income / discounted_total_building_export if discounted_total_building_export > 0 else 0)
|
|
||||||
|
|
||||||
# lcoe of the whole system compining various transactions
|
|
||||||
lcoe_system = (
|
|
||||||
(discounted_total_self_consumption / total_transaction) * lcoe_pv +
|
|
||||||
(discounted_total_grid_purchase / total_transaction) * grid_current_tariff -
|
|
||||||
(discounted_total_building_export / total_transaction) * lcoe_export
|
|
||||||
)
|
|
||||||
|
|
||||||
# NPV calculation
|
|
||||||
npv = total_discounted_income - discounted_total_cost
|
|
||||||
|
|
||||||
return {
|
|
||||||
'LCOE_PV': lcoe_pv,
|
|
||||||
'LCOE_system': lcoe_system,
|
|
||||||
'NPV': npv,
|
|
||||||
'Annual_PV_generation': first_year_generation_PV,
|
|
||||||
'Annual_building_self_consumption': first_year_self_consumption,
|
|
||||||
'Annual_grid_purchase': first_year_grid_purchase,
|
|
||||||
'Annual_PV_export': first_year_PV_export,
|
|
||||||
'Discounted_total_cost': discounted_total_cost,
|
|
||||||
'Total_discounted_income': total_discounted_income,
|
|
||||||
'Discounted_generation_per_year': discounted_generation_per_year,
|
|
||||||
'Discounted_self_consumption_per_year': discounted_self_consumption_per_year,
|
|
||||||
'Discounted_annual_cost': discounted_annual_cost,
|
|
||||||
'Discounted_income_per_year': discounted_income_per_year
|
|
||||||
}
|
|
||||||
|
|
||||||
#example
|
|
Loading…
Reference in New Issue
Block a user