Merge remote-tracking branch 'origin/main'

# Conflicts:
#	main-codes/CMM-PV-20242511.py
This commit is contained in:
Zahra-K-Moraveji 2024-12-04 14:01:56 -05:00
commit 3afd2d9479
8 changed files with 55 additions and 209 deletions

3
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

8
.idea/Gitea.iml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Hub" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.9 (PythonProject6)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Hub" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Gitea.iml" filepath="$PROJECT_DIR$/.idea/Gitea.iml" />
</modules>
</component>
</project>

7
.idea/vcs.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/PV_Economic_Metrics" vcs="Git" />
</component>
</project>

View File

@ -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
#test
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 combining 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

16
main.py Normal file
View File

@ -0,0 +1,16 @@
# This is a sample Python script.
# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
print_hi('PyCharm')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/