Skip to content

Commit

Permalink
Merge pull request #33 from oemof/fix/storage-investment
Browse files Browse the repository at this point in the history
Fix: Storage Investment
  • Loading branch information
jnnr authored Jul 28, 2022
2 parents dadd0af + 641ae45 commit 26c1668
Show file tree
Hide file tree
Showing 7 changed files with 537 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
name;carrier;tech;storage_capacity;capacity;capacity_cost;invest_relation_output_capacity;invest_relation_input_output;expandable;type;bus;tech
el-storage;lithium;battery;;0;10;0.2;1;true;storage;bus0;battery
el-storage;lithium;battery;100;0;10;0.2;1;true;storage;bus0;battery
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@
},
{
"name": "storage_capacity",
"type": "string",
"type": "integer",
"format": "default"
},
{
Expand Down Expand Up @@ -569,4 +569,4 @@
}
}
]
}
}
138 changes: 94 additions & 44 deletions src/oemof/tabular/facades.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,46 +98,83 @@ def _nominal_value(self):
return self.capacity

def _investment(self):
if self.expandable is True:
if self.capacity_cost is None:
msg = (
"If you set `expandable`to True you need to set "
"attribute `capacity_cost` of component {}!"
if not self.expandable:
self.investment = None
return self.investment
if self.capacity_cost is None:
msg = (
"If you set `expandable`to True you need to set "
"attribute `capacity_cost` of component {}!"
)
raise ValueError(msg.format(self.label))
if isinstance(self, GenericStorage):
if self.storage_capacity_cost is not None:
self.investment = Investment(
ep_costs=self.storage_capacity_cost,
maximum=self._get_maximum_additional_invest(
"storage_capacity_potential", "storage_capacity"
),
minimum=getattr(
self, "minimum_storage_capacity", 0
),
existing=getattr(self, "storage_capacity", 0),
)
raise ValueError(msg.format(self.label))
else:
if isinstance(self, GenericStorage):
if self.storage_capacity_cost is not None:
self.investment = Investment(
ep_costs=self.storage_capacity_cost,
maximum=getattr(
self,
"storage_capacity_potential",
float("+inf"),
),
minimum=getattr(
self, "minimum_storage_capacity", 0
),
existing=getattr(self, "storage_capacity", 0),
)
else:
self.investment = Investment()
else:
self.investment = Investment(
ep_costs=self.capacity_cost,
maximum=getattr(
self, "capacity_potential", float("+inf")
),
minimum=getattr(
self, "capacity_minimum", 0
),
existing=getattr(self, "capacity", 0),
)
self.investment = Investment(
maximum=self._get_maximum_additional_invest(
"storage_capacity_potential", "storage_capacity"
),
minimum=getattr(
self, "minimum_storage_capacity", 0
),
existing=getattr(self, "storage_capacity", 0),
)
else:
self.investment = None

self.investment = Investment(
ep_costs=self.capacity_cost,
maximum=self._get_maximum_additional_invest(
"capacity_potential", "capacity"
),
minimum=getattr(
self, "capacity_minimum", 0
),
existing=getattr(self, "capacity", 0),
)
return self.investment

def _get_maximum_additional_invest(self, attr_potential, attr_existing):
r"""
Calculates maximum additional investment by
substracting existing from potential.
Throws an error if existing is larger than potential.
"""
_potential = getattr(
self,
attr_potential,
float("+inf"),
)
_existing = getattr(
self,
attr_existing,
0,
)

if _existing is None:
_existing = 0

if _potential is None:
_potential = float("+inf")

maximum = _potential - _existing

if maximum < 0:
raise ValueError(
f"Existing {attr_existing}={_existing} is larger"
f" than {attr_potential}={_potential}.")

return maximum

def update(self):
self.build_solph_components()

Expand Down Expand Up @@ -374,7 +411,9 @@ def __init__(self, *args, **kwargs):

self.capacity = kwargs.get("capacity")

self.capacity_potential = kwargs.get("capacity_potential")
self.capacity_potential = kwargs.get(
"capacity_potential", float("+inf")
)

self.marginal_cost = kwargs.get("marginal_cost", 0)

Expand Down Expand Up @@ -496,7 +535,10 @@ def __init__(self, *args, **kwargs):

self.capacity = kwargs.get("capacity")

self.capacity_potential = kwargs.get("capacity_potential")
self.capacity_potential = kwargs.get(
"capacity_potential",
float("+inf")
)

self.capacity_minimum = kwargs.get("capacity_minimum")

Expand Down Expand Up @@ -931,7 +973,10 @@ def __init__(self, *args, **kwargs):

self.carrier_cost = kwargs.get("carrier_cost", 0)

self.capacity_potential = kwargs.get("capacity_potential")
self.capacity_potential = kwargs.get(
"capacity_potential",
float("+inf")
)

self.capacity_minimum = kwargs.get("capacity_minimum")

Expand Down Expand Up @@ -995,7 +1040,7 @@ class HeatPump(Transformer, Facade):
expandable: boolean or numeric (binary)
True, if capacity can be expanded within optimization. Default: False.
capacity_potential: numeric
Maximum invest capacity in unit of output capacity.
Maximum invest capacity in unit of output capacity. Default: +inf.
low_temperature_parameters: dict (optional)
Set parameters on the input edge of the heat pump unit
(see oemof.solph for more information on possible parameters)
Expand Down Expand Up @@ -1068,7 +1113,10 @@ def __init__(self, *args, **kwargs):

self.expandable = bool(kwargs.get("expandable", False))

self.capacity_potential = kwargs.get("capacity_potential")
self.capacity_potential = kwargs.get(
"capacity_potential",
float("+inf")
)

self.low_temperature_parameters = kwargs.get(
"low_temperature_parameters", {}
Expand Down Expand Up @@ -1202,9 +1250,9 @@ class Storage(GenericStorage, Facade):
expandable: boolean
True, if capacity can be expanded within optimization. Default: False.
storage_capacity_potential: numeric
Potential of the investment for storage capacity in MWh
Potential of the investment for storage capacity in MWh. Default: +inf.
capacity_potential: numeric
Potential of the investment for capacity in MW
Potential of the investment for capacity in MW. Default: +inf.
input_parameters: dict (optional)
Set parameters on the input edge of the storage (see oemof.solph for
more information on possible parameters)
Expand Down Expand Up @@ -1320,14 +1368,16 @@ def build_solph_components(self):
fi = Flow(
investment=Investment(
ep_costs=self.capacity_cost,
maximum=self.capacity_potential,
maximum=self._get_maximum_additional_invest(
"capacity_potential", "capacity"
),
existing=self.capacity,
),
**self.input_parameters
)
# set investment, but no costs (as relation input / output = 1)
fo = Flow(
investment=Investment(),
investment=Investment(existing=self.capacity),
variable_costs=self.marginal_cost,
**self.output_parameters
)
Expand Down
123 changes: 123 additions & 0 deletions tests/_files/lp_files/storage_investment_brown_field.lp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
\* Source Pyomo model name=Model *\

min
objective:
+1300 GenericInvestmentStorageBlock_invest(storage)
+240 InvestmentFlow_invest(electricity_storage)

s.t.

c_e_Bus_balance(electricity_0)_:
-1 flow(electricity_storage_0)
+1 flow(storage_electricity_0)
= 0

c_e_Bus_balance(electricity_1)_:
-1 flow(electricity_storage_1)
+1 flow(storage_electricity_1)
= 0

c_e_Bus_balance(electricity_2)_:
-1 flow(electricity_storage_2)
+1 flow(storage_electricity_2)
= 0

c_u_InvestmentFlow_max(electricity_storage_0)_:
-1 InvestmentFlow_invest(electricity_storage)
+1 flow(electricity_storage_0)
<= 1

c_u_InvestmentFlow_max(electricity_storage_1)_:
-1 InvestmentFlow_invest(electricity_storage)
+1 flow(electricity_storage_1)
<= 1

c_u_InvestmentFlow_max(electricity_storage_2)_:
-1 InvestmentFlow_invest(electricity_storage)
+1 flow(electricity_storage_2)
<= 1

c_u_InvestmentFlow_max(storage_electricity_0)_:
-1 InvestmentFlow_invest(storage_electricity)
+1 flow(storage_electricity_0)
<= 1

c_u_InvestmentFlow_max(storage_electricity_1)_:
-1 InvestmentFlow_invest(storage_electricity)
+1 flow(storage_electricity_1)
<= 1

c_u_InvestmentFlow_max(storage_electricity_2)_:
-1 InvestmentFlow_invest(storage_electricity)
+1 flow(storage_electricity_2)
<= 1

c_u_GenericInvestmentStorageBlock_init_content_limit(storage)_:
+1 GenericInvestmentStorageBlock_init_content(storage)
-1 GenericInvestmentStorageBlock_invest(storage)
<= 2

c_e_GenericInvestmentStorageBlock_balance_first(storage)_:
-1 GenericInvestmentStorageBlock_init_content(storage)
+1 GenericInvestmentStorageBlock_storage_content(storage_0)
-0.90000000000000002 flow(electricity_storage_0)
+1.1111111111111112 flow(storage_electricity_0)
= 0

c_e_GenericInvestmentStorageBlock_balance(storage_1)_:
-1 GenericInvestmentStorageBlock_storage_content(storage_0)
+1 GenericInvestmentStorageBlock_storage_content(storage_1)
-0.90000000000000002 flow(electricity_storage_1)
+1.1111111111111112 flow(storage_electricity_1)
= 0

c_e_GenericInvestmentStorageBlock_balance(storage_2)_:
-1 GenericInvestmentStorageBlock_storage_content(storage_1)
+1 GenericInvestmentStorageBlock_storage_content(storage_2)
-0.90000000000000002 flow(electricity_storage_2)
+1.1111111111111112 flow(storage_electricity_2)
= 0

c_e_GenericInvestmentStorageBlock_balanced_cstr(storage)_:
-1 GenericInvestmentStorageBlock_init_content(storage)
+1 GenericInvestmentStorageBlock_storage_content(storage_2)
= 0

c_e_GenericInvestmentStorageBlock_power_coupled(storage)_:
-1 InvestmentFlow_invest(electricity_storage)
+1 InvestmentFlow_invest(storage_electricity)
= 0

c_u_GenericInvestmentStorageBlock_max_storage_content(storage_0)_:
-1 GenericInvestmentStorageBlock_invest(storage)
+1 GenericInvestmentStorageBlock_storage_content(storage_0)
<= 2

c_u_GenericInvestmentStorageBlock_max_storage_content(storage_1)_:
-1 GenericInvestmentStorageBlock_invest(storage)
+1 GenericInvestmentStorageBlock_storage_content(storage_1)
<= 2

c_u_GenericInvestmentStorageBlock_max_storage_content(storage_2)_:
-1 GenericInvestmentStorageBlock_invest(storage)
+1 GenericInvestmentStorageBlock_storage_content(storage_2)
<= 2

c_e_ONE_VAR_CONSTANT:
ONE_VAR_CONSTANT = 1.0

bounds
0 <= flow(electricity_storage_0) <= +inf
0 <= flow(electricity_storage_1) <= +inf
0 <= flow(electricity_storage_2) <= +inf
0 <= flow(storage_electricity_0) <= +inf
0 <= flow(storage_electricity_1) <= +inf
0 <= flow(storage_electricity_2) <= +inf
0 <= InvestmentFlow_invest(electricity_storage) <= 4
0 <= InvestmentFlow_invest(storage_electricity) <= +inf
0 <= GenericInvestmentStorageBlock_storage_content(storage_0) <= +inf
0 <= GenericInvestmentStorageBlock_storage_content(storage_1) <= +inf
0 <= GenericInvestmentStorageBlock_storage_content(storage_2) <= +inf
0 <= GenericInvestmentStorageBlock_invest(storage) <= 8
0 <= GenericInvestmentStorageBlock_init_content(storage) <= +inf
end
Loading

0 comments on commit 26c1668

Please sign in to comment.