The energy model is structured as follows and uses excel sheets to give input data:
- Utility.py contains all the functions needed to calculate the variables and other minor things (mentions interest rate in two functions)
- ModelSettings.py is in charge of setting the model data, here you specify the structure of the data (mentions interest rate in two identical structures for the transmission lines and the regional parameters)
- Excel.py reads the ModelSettings.py, writes the excel files and then once they are populated it reads the date and passes them to ModelData.py
- ModelData.py does some checks and stores the data.
- ModelVariables.py calculates the variables of the problem using ModelData.py and the functions in Utility.py
- These are then called by Build.py that has the objective function, then there is Main.py that launches the model and other scripts that i believe are not relevant.
I have modified the ModelSetting.py changing the interest_rate declaration and coping it from investments costs that are defined for every year, every technology and every region as follows:
original:
if self.mode == ModelMode.Planning:
connection_parameters_template.update(
...
"interest_rate": {
"sheet_name": "Interest_rate",
"value": 0.05,
"index": pd.Index(
["Interest Rate"], name="Performance Parameter"
),
"columns": indexer,
},
...
modified:
"interest_rate": {
"sheet_name": "Interest_rate",
"value": 0.05,
"index": pd.Index(self.years, name="Years"), #GA modified
"columns": indexer,
},
This works and gives me the excel file with the correct structure.
Then I have modified ModelVariables.py, again coping from investments:
Original:
for key in self.new_capacity[reg].keys():
real_new_capacity_regional[key] = shift_new_cap(
self.new_capacity[reg][key],
self.model_data.settings.technologies[reg][key],
self.model_data.regional_parameters[reg]["time_of_construction"].loc[:, key],
self.model_data.settings.years)
(
cost_inv_regional[key],
cost_inv_tax_regional[key],
cost_inv_sub_regional[key],
) = invcosts(
self.model_data.regional_parameters[reg]["tech_inv"][key],
self.new_capacity[reg][key],
self.model_data.regional_parameters[reg]["inv_taxsub"]["Tax"][key],
self.model_data.regional_parameters[reg]["inv_taxsub"]["Sub"][key],
)
salvage_inv_regional[key] = cp.multiply(
salvage_factor(
self.model_data.settings.years,
self.model_data.settings.technologies[reg][key],
self.model_data.regional_parameters[reg]["tech_lifetime"].loc[:, key],
self.model_data.regional_parameters[reg]["interest_rate"].loc[:, key],
self.model_data.regional_parameters[reg]["discount_rate"],
self.model_data.regional_parameters[reg]["economic_lifetime"].loc[:, key],
),
cost_inv_regional[key],
)
modified:
for key in self.new_capacity[reg].keys():
real_new_capacity_regional[key] = shift_new_cap(
self.new_capacity[reg][key],
self.model_data.settings.technologies[reg][key],
self.model_data.regional_parameters[reg]["time_of_construction"].loc[:, key],
self.model_data.settings.years)
(
cost_inv_regional[key],
cost_inv_tax_regional[key],
cost_inv_sub_regional[key],
) = invcosts(
self.model_data.regional_parameters[reg]["tech_inv"][key],
self.new_capacity[reg][key],
self.model_data.regional_parameters[reg]["inv_taxsub"]["Tax"][key],
self.model_data.regional_parameters[reg]["inv_taxsub"]["Sub"][key],
)
salvage_inv_regional[key] = cp.multiply(
salvage_factor(
self.model_data.settings.years,
self.model_data.settings.technologies[reg][key],
self.model_data.regional_parameters[reg]["tech_lifetime"].loc[:, key],
self.model_data.regional_parameters[reg]["interest_rate"][key], #GA modify
self.model_data.regional_parameters[reg]["discount_rate"],
self.model_data.regional_parameters[reg]["economic_lifetime"].loc[:, key],
),
cost_inv_regional[key],
)
Now if i do not change the utility function where it uses the interest rate it gives me the error:
File ~/anaconda3/envs/hypatia/lib/python3.9/site-packages/pandas/core/indexing.py:1941 in _setitem_with_indexer_2d_value
raise ValueError(
ValueError: Must have equal len keys and value when setting with an ndarray
This are the original two functions:
the first one:
def invcosts_annuity(
cost_inv_present,
interest_rate,
economiclife,
technologies,
main_years,
discount_rate,
):
"""
Calculates the annuities of the investment costs based on the interest rate
and economic lifetime of each technology
"""
depreciation = np.divide(
np.multiply(
np.power((interest_rate.values + 1), economiclife.values),
interest_rate.values,
),
(np.power((interest_rate.values + 1), economiclife.values) - 1),
)
depreciation = pd.DataFrame(
depreciation, index=["Depreciation_rate"], columns=technologies
)
inv_fvalue_total = 0
for tech_indx, tech in enumerate(technologies):
inv_fvalue_discounted = 0
for y_indx, year in enumerate(main_years):
inv_fvalue_annual_discounted = 0
for future_year in range(
y_indx + 1, y_indx + economiclife.loc["Economic Life time", tech] + 1
):
annuity = (
cost_inv_present[y_indx, tech_indx]
* depreciation.loc["Depreciation_rate", tech]
)
inv_fvalue_annual_discounted += annuity * (
1 + discount_rate.loc[year, "Annual Discount Rate"]
) ** (-future_year)
inv_fvalue_discounted += inv_fvalue_annual_discounted
inv_fvalue_total += inv_fvalue_discounted
return inv_fvalue_total
And the second one:
def salvage_factor(
main_years, technologies, tlft, interest_rate, discount_rate, economiclife
):
"""
Calculates the salvage factor of the investment cost for the capacities
that remain after the end of the time horizon to avoid the end of the horizon
effect
"""
salvage_factor_0 = pd.DataFrame(0, index=main_years, columns=technologies)
rates_factor = pd.DataFrame(0, index=main_years, columns=technologies)
EOH = len(main_years) - 1
for tech in technologies:
technical_factor = (1 - 1 / (1 + interest_rate[tech].values)) / (
1 - 1 / ((1 + interest_rate[tech].values) ** economiclife[tech].values)
)
social_factor = (
1 - 1 / ((1 + discount_rate.values) ** economiclife[tech].values)
) / (1 - 1 / (1 + discount_rate.values))
rates_factor.loc[:, tech] = technical_factor * social_factor
for indx, year in enumerate(main_years):
if indx + tlft[tech].values > EOH:
salvage_factor_0.loc[year, tech] = (
(1 + discount_rate.loc[year, :].values)
** (tlft[tech].values - EOH - 1 + indx)
- 1
) / ((1 + discount_rate.loc[year, :].values) ** tlft[tech].values - 1)
salvage_factor_mod = pd.DataFrame(
salvage_factor_0.values * rates_factor.values,
index=main_years,
columns=technologies,
)
return salvage_factor_mod
Please help me to modify these two functions so that they can use the new interest rate.