Python Forum

Full Version: Modify an Energy Model to account for year dependent interest rate rather than only t
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
The energy model is structured as follows and uses excel sheets to give input data:

1.Utility.py contains all the functions needed to calculate the variables and other minor things (mentions interest rate in two functions)
2.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)
3.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
4.ModelData.py does some checks and stores the data.
5.ModelVariables.py calculates the variables of the problem using ModelData.py and the functions in Utility.py
6.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
The second:
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.