Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust indexing for content of InvestStorageBlock #1039

Merged
merged 5 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 85 additions & 74 deletions src/oemof/solph/components/_generic_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ def _balanced_storage_rule(block, n):
self.STORAGES_BALANCED, rule=_balanced_storage_rule
)

def _power_coupled(block):
def _power_coupled(_):
"""
Rule definition for constraint to connect the input power
and output power
Expand Down Expand Up @@ -1215,7 +1215,7 @@ def _create(self, group=None):

# ######################### Variables ################################
self.storage_content = Var(
self.INVESTSTORAGES, m.TIMESTEPS, within=NonNegativeReals
self.INVESTSTORAGES, m.TIMEPOINTS, within=NonNegativeReals
)

def _storage_investvar_bound_rule(block, n, p):
Expand Down Expand Up @@ -1272,8 +1272,6 @@ def _storage_investvar_bound_rule(block, n, p):
i = {n: [i for i in n.inputs][0] for n in group}
o = {n: [o for o in n.outputs][0] for n in group}

reduced_periods_timeindex = [(p, t) for (p, t) in m.TIMEINDEX if t > 0]

# Handle unit lifetimes
def _total_storage_capacity_rule(block):
"""Rule definition for determining total installed
Expand Down Expand Up @@ -1463,7 +1461,7 @@ def _old_storage_capacity_rule(block):

self.old_rule_build = BuildAction(rule=_old_storage_capacity_rule)

def _initially_empty_rule(block):
def _initially_empty_rule(_):
"""Ensure storage to be empty initially"""
for n in self.INVESTSTORAGES:
expr = self.storage_content[n, 0] == 0
Expand Down Expand Up @@ -1494,7 +1492,9 @@ def _inv_storage_init_content_max_rule(block, n):

def _inv_storage_init_content_fix_rule(block, n):
"""Constraint for a fixed initial storage capacity."""
return block.init_content[n] == n.initial_storage_level * (
return block.storage_content[
n, 0
] == n.initial_storage_level * (
n.investment.existing + block.invest[n, 0]
)

Expand All @@ -1503,44 +1503,15 @@ def _inv_storage_init_content_fix_rule(block, n):
rule=_inv_storage_init_content_fix_rule,
)

def _storage_balance_first_rule(block, n):
"""
Rule definition for the storage balance of every storage n
for the first time step.
"""
expr = 0
expr += block.storage_content[n, 0]
expr += (
-block.init_content[n]
* (1 - n.loss_rate[0]) ** m.timeincrement[0]
)
expr += (
n.fixed_losses_relative[0]
* (n.investment.existing + self.invest[n, 0])
* m.timeincrement[0]
)
expr += n.fixed_losses_absolute[0] * m.timeincrement[0]
expr += (
-m.flow[i[n], n, 0] * n.inflow_conversion_factor[0]
) * m.timeincrement[0]
expr += (
m.flow[n, o[n], 0] / n.outflow_conversion_factor[0]
) * m.timeincrement[0]
return expr == 0

self.balance_first = Constraint(
self.INVESTSTORAGES, rule=_storage_balance_first_rule
)

def _storage_balance_rule(block, n, p, t):
"""
Rule definition for the storage balance of every storage n
for every time step but the first.
Rule definition for the storage balance of every storage n and
every timestep.
"""
expr = 0
expr += block.storage_content[n, t]
expr += block.storage_content[n, t + 1]
expr += (
-block.storage_content[n, t - 1]
-block.storage_content[n, t]
* (1 - n.loss_rate[t]) ** m.timeincrement[t]
)
expr += (
Expand All @@ -1559,7 +1530,7 @@ def _storage_balance_rule(block, n, p, t):

self.balance = Constraint(
self.INVESTSTORAGES,
reduced_periods_timeindex,
m.TIMEINDEX,
rule=_storage_balance_rule,
)

Expand Down Expand Up @@ -1639,40 +1610,7 @@ def _storage_capacity_outflow_invest_rule(block):
rule=_storage_capacity_outflow_invest_rule
)

def _max_storage_content_invest_rule(block, n, p, t):
"""
Rule definition for upper bound constraint for the
storage content.
"""
expr = (
self.storage_content[n, t]
<= self.total[n, p] * n.max_storage_level[t]
)
return expr

self.max_storage_content = Constraint(
self.INVESTSTORAGES,
m.TIMEINDEX,
rule=_max_storage_content_invest_rule,
)

def _min_storage_content_invest_rule(block, n, p, t):
"""
Rule definition of lower bound constraint for the
storage content.
"""
expr = (
self.storage_content[n, t]
>= self.total[n, p] * n.min_storage_level[t]
)
return expr

# Set the lower bound of the storage content if the attribute exists
self.min_storage_content = Constraint(
self.MIN_INVESTSTORAGES,
m.TIMEINDEX,
rule=_min_storage_content_invest_rule,
)
self._add_storage_limit_constraints()

def maximum_invest_limit(block, n, p):
"""
Expand Down Expand Up @@ -1746,6 +1684,79 @@ def _overall_minimum_investflow_rule(block):
rule=_overall_minimum_investflow_rule
)

def _add_storage_limit_constraints(self):
m = self.parent_block()
if m.es.periods is None:

def _max_storage_content_invest_rule(_, n, t):
"""
Rule definition for upper bound constraint for the
storage content.
"""
expr = (
self.storage_content[n, t]
<= self.total[n, 0] * n.max_storage_level[t]
)
return expr

self.max_storage_content = Constraint(
self.INVESTSTORAGES,
m.TIMEPOINTS,
rule=_max_storage_content_invest_rule,
)

def _min_storage_content_invest_rule(_, n, t):
"""
Rule definition of lower bound constraint for the
storage content.
"""
expr = (
self.storage_content[n, t]
>= self.total[n, 0] * n.min_storage_level[t]
)
return expr

self.min_storage_content = Constraint(
self.MIN_INVESTSTORAGES,
m.TIMEPOINTS,
rule=_min_storage_content_invest_rule,
)
else:

def _max_storage_content_invest_rule(_, n, p, t):
"""
Rule definition for upper bound constraint for the
storage content.
"""
expr = (
self.storage_content[n, t]
<= self.total[n, p] * n.max_storage_level[t]
)
return expr

self.max_storage_content = Constraint(
self.INVESTSTORAGES,
m.TIMEINDEX,
rule=_max_storage_content_invest_rule,
)

def _min_storage_content_invest_rule(_, n, p, t):
"""
Rule definition of lower bound constraint for the
storage content.
"""
expr = (
self.storage_content[n, t]
>= self.total[n, p] * n.min_storage_level[t]
)
return expr

self.min_storage_content = Constraint(
self.MIN_INVESTSTORAGES,
m.TIMEINDEX,
rule=_min_storage_content_invest_rule,
)

def _objective_expression(self):
"""Objective expression with fixed and investment costs."""
m = self.parent_block()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def test_optimise_storage_size(
es.dump()


def test_results_with_actual_dump():
def test_results_with_recent_dump():
test_optimise_storage_size()
energysystem = solph.EnergySystem()
energysystem.restore()
Expand Down Expand Up @@ -196,7 +196,7 @@ def test_results_with_actual_dump():
# Problem results
assert meta["problem"]["Lower bound"] == 4.231675777e17
assert meta["problem"]["Upper bound"], 4.231675777e17
assert meta["problem"]["Number of variables"] == 2807
assert meta["problem"]["Number of variables"] == 2808
assert meta["problem"]["Number of constraints"] == 2808
assert meta["problem"]["Number of nonzeros"] == 1197
assert meta["problem"]["Number of objectives"] == 1
Expand Down
Loading