Skip to content

Commit

Permalink
discounted cost by storage
Browse files Browse the repository at this point in the history
  • Loading branch information
trevorb1 committed Nov 8, 2024
1 parent 39c6ae4 commit 5f13fc2
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/otoole/results/result_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def __init__(
"Demand": self.demand,
"DiscountedCapitalInvestment": self.discounted_capital_investment,
"DiscountedCapitalInvestmentStorage": self.discounted_capital_investment_storage,
"DiscountedCostByStorage": self.discounted_storage_cost,
"DiscountedCostByTechnology": self.discounted_technology_cost,
"DiscountedOperationalCost": self.discounted_operational_cost,
"DiscountedSalvageValueStorage": self.discounted_salvage_value_storage,
Expand Down Expand Up @@ -590,6 +591,49 @@ def discounted_operational_cost(self) -> pd.DataFrame:

return data[(data != 0).all(1)]

def discounted_storage_cost(self) -> pd.DataFrame:
"""TotalDiscountedCostByStorage
Notes
-----
From the formulation::
r~REGION, s~STORAGE, y~YEAR,
TotalDiscountedStorageCost[r,s,y]:=
(
CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y] / DiscountFactorStorage[r,s,y] -
SalvageValueStorage[r,s,y] /
(
(1+DiscountRateStorage[r,s])^(max{yy in YEAR} max(yy)-min{yy in YEAR} min(yy)+1))
)
)
Alternatively, can be written as::
r~REGION, s~STORAGE, y~YEAR,
TotalDiscountedStorageCost[r,s,y]:=
DiscountedCapitalInvestmentStorage[r,s,y] - DiscountedSalvageValueStorage[r,s,y]
"""

try:
discounted_capital_investment_storage = self[
"DiscountedCapitalInvestmentStorage"
]
discounted_salvage_value_storage = self["DiscountedSalvageValueStorage"]

except KeyError as ex:
raise KeyError(self._msg("TotalDiscountedCostByStorage", str(ex)))

discounted_storage_costs = discounted_capital_investment_storage.sub(
discounted_salvage_value_storage, fill_value=0.0
)

data = discounted_storage_costs

if not data.empty:
data = data.groupby(by=["REGION", "STORAGE", "YEAR"]).sum()
return data[(data != 0).all(1)]

def discounted_salvage_value_storage(self) -> pd.DataFrame:
"""DiscountedSalvageValueStorage
Expand Down
86 changes: 86 additions & 0 deletions tests/results/test_results_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,53 @@ def salvage_value_storage():
return data


@fixture
def discounted_capital_costs_storage():
data = pd.DataFrame(
data=[
["SIMPLICITY", "BATTERY", 2014, 11.1],
["SIMPLICITY", "BATTERY", 2016, 22.2],
["SIMPLICITY", "DAM", 2014, 33.3],
["SIMPLICITY", "DAM", 2015, 44.4],
["SIMPLICITY", "DAM", 2016, 55.5],
],
columns=["REGION", "STORAGE", "YEAR", "VALUE"],
).set_index(["REGION", "STORAGE", "YEAR"])
return data


@fixture
def discounted_salvage_value_storage():
data = pd.DataFrame(
data=[
["SIMPLICITY", "DAM", 2014, 1.23],
["SIMPLICITY", "DAM", 2015, 2.34],
["SIMPLICITY", "DAM", 2016, 3.45],
["SIMPLICITY", "BATTERY", 2014, 4.56],
["SIMPLICITY", "BATTERY", 2015, 5.67],
["SIMPLICITY", "BATTERY", 2016, 6.78],
],
columns=["REGION", "STORAGE", "YEAR", "VALUE"],
).set_index(["REGION", "STORAGE", "YEAR"])
return data


@fixture
def discounted_storage_cost():
data = pd.DataFrame(
data=[
["SIMPLICITY", "DUMMY", 2014, 111],
["SIMPLICITY", "DUMMY", 2015, 222],
["SIMPLICITY", "DUMMY", 2016, 333],
["SIMPLICITY", "GAS_EXTRACTION", 2014, 444],
["SIMPLICITY", "GAS_EXTRACTION", 2015, 555],
["SIMPLICITY", "GAS_EXTRACTION", 2016, 666],
],
columns=["REGION", "TECHNOLOGY", "YEAR", "VALUE"],
).set_index(["REGION", "TECHNOLOGY", "YEAR"])
return data


@fixture(scope="function")
def null() -> ResultsPackage:
package = ResultsPackage({})
Expand Down Expand Up @@ -1129,6 +1176,45 @@ def test_null(self, null: ResultsPackage):
)


class TestDiscountedCostByStorage:
def test_calculate_discounted_cost_by_storage(
self,
discounted_capital_costs_storage,
discounted_salvage_value_storage,
):

results = {
"DiscountedCapitalInvestmentStorage": discounted_capital_costs_storage,
"DiscountedSalvageValueStorage": discounted_salvage_value_storage,
}

package = ResultsPackage(results)
actual = package.discounted_storage_cost()
expected = pd.DataFrame(
data=[
["SIMPLICITY", "BATTERY", 2014, 6.54],
["SIMPLICITY", "BATTERY", 2015, -5.67],
["SIMPLICITY", "BATTERY", 2016, 15.42],
["SIMPLICITY", "DAM", 2014, 32.07],
["SIMPLICITY", "DAM", 2015, 42.06],
["SIMPLICITY", "DAM", 2016, 52.05],
],
columns=["REGION", "STORAGE", "YEAR", "VALUE"],
).set_index(["REGION", "STORAGE", "YEAR"])

assert_frame_equal(actual, expected)

def test_null(self, null: ResultsPackage):
""" """
package = null
with raises(KeyError) as ex:
package.discounted_storage_cost()
assert (
"Cannot calculate TotalDiscountedCostByStorage due to missing data"
in str(ex)
)


class TestTotalDiscountedCost:
def test_calculate_total_discounted_cost(
self,
Expand Down

0 comments on commit 5f13fc2

Please sign in to comment.