From 903f9b4a2e50cf1e0e0691de1db24adfdce1a9b9 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Mon, 21 Aug 2023 07:56:28 +0200 Subject: [PATCH 001/180] Replace setup.py invocation by build --- .github/workflows/packaging.yml | 4 ++-- tox.ini | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index 68e876b30..b3601dfb9 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -26,9 +26,9 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip setuptools setuptools_scm twine wheel + python -m pip install --upgrade pip setuptools setuptools_scm twine wheel build - name: Create packages - run: python setup.py sdist bdist_wheel + run: python -m build . - name: Run twine check run: twine check dist/* - uses: actions/upload-artifact@v2 diff --git a/tox.ini b/tox.ini index a7b080859..b1fe2caf9 100644 --- a/tox.ini +++ b/tox.ini @@ -50,7 +50,7 @@ deps = isort skip_install = true commands = - python setup.py sdist + python -m build . twine check dist/oemof* check-manifest {toxinidir} flake8 src tests setup.py From 379a1e403ec81b11f6f9c421916fd728d73bae43 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Mon, 21 Aug 2023 07:59:25 +0200 Subject: [PATCH 002/180] Add build dependency to check workflow --- .github/workflows/tox_checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tox_checks.yml b/.github/workflows/tox_checks.yml index f84eb1c2c..8686b132f 100644 --- a/.github/workflows/tox_checks.yml +++ b/.github/workflows/tox_checks.yml @@ -49,7 +49,7 @@ jobs: - name: Install dependencies run: | python -m pip install -U pip - python -m pip install -U setuptools wheel + python -m pip install -U setuptools wheel build python -m pip install -U tox - name: Run ${{ matrix.toxenv }} From 1290c05bbd7d4293951cbeeaed98f669603356ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 31 Aug 2023 12:19:34 +0200 Subject: [PATCH 003/180] Prepare for development towards 0.5.2 --- .bumpversion.cfg | 2 +- VERSION | 2 +- docs/changelog.rst | 1 + docs/conf.py | 2 +- docs/whatsnew/v0-5-2.rst | 23 +++++++++++++++++++++++ setup.py | 2 +- src/oemof/solph/__init__.py | 2 +- 7 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 docs/whatsnew/v0-5-2.rst diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 867d689ee..8de708172 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.5.1 +current_version = 0.5.2dev0 commit = True tag = True diff --git a/VERSION b/VERSION index dd9b22ccc..669e6f35c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -__version__ = "0.5.1" +__version__ = "0.5.2dev0" diff --git a/docs/changelog.rst b/docs/changelog.rst index a7815ef88..da0b2f4a9 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,6 +9,7 @@ These are new features and improvements of note in each release :backlinks: top +.. include:: whatsnew/v0-5-2.rst .. include:: whatsnew/v0-5-1.rst .. include:: whatsnew/v0-5-0.rst .. include:: whatsnew/v0-4-5.rst diff --git a/docs/conf.py b/docs/conf.py index 12972c768..05665cac1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,7 @@ def setup(app): year = "2014-2023" author = "oemof-developer-group" copyright = "{0}, {1}".format(year, author) -version = release = "0.5.1" +version = release = "0.5.2dev0" pygments_style = "trac" templates_path = ["."] diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst new file mode 100644 index 000000000..d9d20b7be --- /dev/null +++ b/docs/whatsnew/v0-5-2.rst @@ -0,0 +1,23 @@ +v0.5.2 (????) +------------- + +API changes +########### + +New features +############ + +Documentation +############# + +Bug fixes +######### + +Testing +####### + +Other changes +############# + +Contributors +############ diff --git a/setup.py b/setup.py index 8bbc36a0a..392b3d1b0 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ def read(*names, **kwargs): setup( name="oemof.solph", - version="0.5.1", + version="0.5.2dev0", license="MIT", description=( "A model generator for energy system modelling and optimisation." diff --git a/src/oemof/solph/__init__.py b/src/oemof/solph/__init__.py index d96fb5ed1..4ea8f8a15 100644 --- a/src/oemof/solph/__init__.py +++ b/src/oemof/solph/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.5.1" +__version__ = "0.5.2dev0" from . import buses from . import components From ee85749e3030a263c8dadd0e2721aec60b863017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 31 Aug 2023 12:29:36 +0200 Subject: [PATCH 004/180] Count commits since release in README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 6151423e1..ef893ebe4 100644 --- a/README.rst +++ b/README.rst @@ -63,7 +63,7 @@ .. |commits-since| image:: https://img.shields.io/github/commits-since/oemof/oemof-solph/v0.5.0/dev :alt: Commits since latest release - :target: https://github.com/oemof/oemof-solph/compare/v0.5.0...dev + :target: https://github.com/oemof/oemof-solph/compare/v0.5.1...dev .. |zenodo| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.596235.svg :alt: Zenodo DOI From f02297ea7db0134bfff12c3ff6c7c909ca4405ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 31 Aug 2023 12:32:21 +0200 Subject: [PATCH 005/180] Count commits since 0.5.1 in readme --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index ef893ebe4..e5d724db9 100644 --- a/README.rst +++ b/README.rst @@ -61,7 +61,7 @@ :alt: Supported implementations :target: https://pypi.org/project/oemof.solph -.. |commits-since| image:: https://img.shields.io/github/commits-since/oemof/oemof-solph/v0.5.0/dev +.. |commits-since| image:: https://img.shields.io/github/commits-since/oemof/oemof-solph/v0.5.1/dev :alt: Commits since latest release :target: https://github.com/oemof/oemof-solph/compare/v0.5.1...dev From c14f4ae0bf557721863bcaae6d34fa2933655d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 11 Sep 2023 20:31:03 +0200 Subject: [PATCH 006/180] Fix doc still refered to create_year_index The function has been renamed some time ago. --- docs/usage.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index 32b8e3741..45a649632 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -61,7 +61,7 @@ The model time is defined by the number of intervals and the length of intervals The index will also be used for the results. For a numeric index the resulting time series will indexed with a numeric index starting with 0. One can use the function -:py:func:`~oemof.solph._energy_system/create_year_index` to create an equidistant datetime index. By default the function creates an hourly index for one year, so online the year has to be passed to the function. But it is also possible to change the length of the interval to quarter hours etc.. The default number of intervals is the number needed to cover the given year but the value can be overwritten by the user. +:py:func:`create_time_index` to create an equidistant datetime index. By default the function creates an hourly index for one year, so online the year has to be passed to the function. But it is also possible to change the length of the interval to quarter hours etc.. The default number of intervals is the number needed to cover the given year but the value can be overwritten by the user. It is also possible to define the datetime index using pandas. See `pandas date_range guide `_ for more information. @@ -69,8 +69,8 @@ Both code blocks will create an hourly datetime index for 2011: .. code-block:: python - from oemof.solph import create_year_index - my_index = create_year_index(2011) + from oemof.solph import create_time_index + my_index = create_time_index(2011) .. code-block:: python From 3167edc097bdb03954b72906ba6814a46f70365b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 11 Sep 2023 20:41:53 +0200 Subject: [PATCH 007/180] Speak of "example applications" in README The word "Examples" is used for a headine of another level in the documentation. Also, reference to the examples repository is removed as it is no longer a prefered source. --- README.rst | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 6151423e1..f13d2c535 100644 --- a/README.rst +++ b/README.rst @@ -252,19 +252,14 @@ The core ideas of oemof as a whole are described in (preprint at `arXiv:1808.0807 `_). To allow citing specific versions, we use the zenodo project to get a DOI for each version. - -.. _solph_examples_label: - -Examples -======== +Example Applications +==================== The combination of specific modules (often including other packages) is called an application (app). For example, it can depict a concrete energy system model. You can find a large variety of helpful examples in the documentation. The examples show the optimisation of different energy systems and are supposed to help new users to understand the framework's structure. -There is some elaboration on the examples in the respective repository. -The repository has sections for each major release. You are welcome to contribute your own examples via a `pull request `_ or by e-mailing us (see `here `_ for contact information). From 4f2b64cf5fcfb7fe4e90623926711c197a55324c Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Mon, 2 Oct 2023 15:55:38 +0200 Subject: [PATCH 008/180] Add minor bug fix --- src/oemof/solph/flows/_investment_flow_block.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 9ee4122e3..f763d2c7e 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -316,7 +316,7 @@ def _create_constraints(self): & else:\\ & - P_{old,end}(p)\\ + P_{old,end}(p) = 0\\ &\\ & if \quad p=0:\\ @@ -529,7 +529,7 @@ def _old_capacity_rule_end(block): # multiple invests can be decommissioned in the same period # but only sequential ones, thus a bookkeeping is - # introduced andconstraints are added to equation one + # introduced and constraints are added to equation one # iteration later. last_decomm_p = np.nan # loop over invest periods (values are decomm_periods) From b61d11fb2f42e417786688f4221d283b2f376d17 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Mon, 2 Oct 2023 16:06:54 +0200 Subject: [PATCH 009/180] Replace "simulation" by "optimization" --- src/oemof/solph/_energy_system.py | 4 ++-- src/oemof/solph/_options.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index a2a166fb5..5b177b433 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -176,12 +176,12 @@ def __init__( self._extract_periods_matrix() def _extract_periods_years(self): - """Map simulation years to the respective period based on time indices + """Map years in optimization to respective period based on time indices Returns ------- periods_years: dict - the simulation year of the start of each a period, + year of the start of each period, relative to the start of the optimization run and starting with 0 """ periods_years = [0] diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index 051eb8479..42bf15885 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -62,7 +62,7 @@ class Investment: Units lifetime, given in years; only applicable for multi-period models age : int, :math:`a` - Units start age, given in years at the beginning of the simulation; + Units start age, given in years at the beginning of the optimization; only applicable for multi-period models interest_rate : float, :math:`ir` Interest rate for calculating annuities when investing in a particular From de93c31348a42058930ad2d47c9c1017a7bc52da Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Mon, 2 Oct 2023 16:07:23 +0200 Subject: [PATCH 010/180] fix erroneous type and methods in multi-period usage docs; add hint to timeincrement --- docs/usage.rst | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index 32b8e3741..c8f0c5f0f 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1004,8 +1004,8 @@ mathematical background, like variables and constraints, which are used. .. _multi_period_mode_label: -Using the multi-period (investment) mode (experimental) -------------------------------------------------------- +Multi-period (investment) mode (experimental) +--------------------------------------------- Sometimes you might be interested in how energy systems could evolve in the longer-term, e.g. until 2045 or 2050 to meet some carbon neutrality and climate protection or RES and energy efficiency targets. @@ -1020,7 +1020,7 @@ only unfolds if you look at long-term investments. Let's see how. First, you start by defining your energy system as you might have done before, but you * choose a longer-term time horizon (spanning multiple years, i.e. multiple periods) and -* explicitly define the `periods` attribute of your energy system which maps time steps to the simulated period. +* explicitly define the `periods` attribute of your energy system which lists the time steps for each period. .. code-block:: python @@ -1028,10 +1028,10 @@ First, you start by defining your energy system as you might have done before, b import oemof.solph as solph my_index = pd.date_range('1/1/2013', periods=17520, freq='H') - periods = { - 0: pd.date_range('1/1/2013', periods=8760, freq='H'), - 1: pd.date_range('1/1/2014', periods=8760, freq='H'), - } + periods = [ + pd.date_range('1/1/2013', periods=8760, freq='H'), + pd.date_range('1/1/2014', periods=8760, freq='H'), + ] my_energysystem = solph.EnergySystem(timeindex=my_index, periods=periods) If you want to use a multi-period model you have define periods of your energy system explicitly. This way, @@ -1057,17 +1057,16 @@ and adjust to your needs: Returns ------- - periods : dict - pd.date_ranges defining the time stamps for the respective period, - starting with period 0 + periods : list + periods for the optimization run """ years = sorted(list(set(getattr(datetimeindex, "year")))) - periods = {} + periods = [] filter_series = datetimeindex.to_series() for number, year in enumerate(years): start = filter_series.loc[filter_series.index.year == year].min() end = filter_series.loc[filter_series.index.year == year].max() - periods[number] = pd.date_range(start, end, freq=datetimeindex.freq) + periods.append(pd.date_range(start, end, freq=datetimeindex.freq)) return periods @@ -1269,6 +1268,8 @@ Besides the `invest` variable, new variables are introduced as well. These are: * You can specify periods of different lengths, but the frequency of your timeindex needs to be consistent. Also, you could use the `timeincrement` attribute of the energy system to model different weightings. Be aware that this has not yet been tested. + * For now, both, the `timeindex` as well as the `timeincrement` of an energy system have to be defined since they + have to be of the same length for a multi-period model. * Also please be aware, that periods correspond to years by default. You could also choose monthly periods, but you would need to be very careful in parameterizing your energy system and your model and also, this would mean monthly discounting (if applicable) as well as specifying your plants lifetimes in months. From 5ad6f86f38258b91ed334532a79422f3a18d9dee Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Mon, 2 Oct 2023 16:11:37 +0200 Subject: [PATCH 011/180] Correct changelog information --- docs/whatsnew/v0-5-1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/whatsnew/v0-5-1.rst b/docs/whatsnew/v0-5-1.rst index 1922d23ab..06c327774 100644 --- a/docs/whatsnew/v0-5-1.rst +++ b/docs/whatsnew/v0-5-1.rst @@ -23,8 +23,8 @@ New features * Add option to run multi-period (dynamic) investment models with oemof.solph as an experimental feature: * You can change from standard model to multi-period model by defining the newly introduced `periods` - attribute of your energy system. Be aware that it is experimental as of now. `periods` is a dictionary - mapping the periods you want to model (usually years) to pandas.date_range objects. + attribute of your energy system. Be aware that it is experimental as of now. `periods` is a list + of the periods you want to model (usually years) given as pandas.date_range objects. * Add attributes `periods` to :class:`oemof.solph._energy_system.EnergySystem`. * Introduce new Pyomo Sets `PERIODS` and `TIMEINDEX` in :class:`oemof.solph.models.Model`. * Index all investment-related variables with `PERIODS` and flow variable with `TIMEINDEX`, which From aa15956a0d41571e4cf8d602a2a520a8bff9bc78 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Mon, 2 Oct 2023 17:06:30 +0200 Subject: [PATCH 012/180] Account for remaining values and limit fixed costs to optimization horizon in invest flow --- .../solph/flows/_investment_flow_block.py | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 9ee4122e3..817a9be78 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -887,6 +887,24 @@ def _objective_expression(self): * lifetime * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) ) + remaining_value = 0 + if lifetime > m.es.periods_matrix[p, -1]: + remaining_lifetime = ( + lifetime - m.es.periods_matrix[p, -1] + ) + remaining_annuity = economics.annuity( + capex=m.flows[i, o].investment.ep_costs[-1], + n=lifetime, + wacc=interest, + ) + remaining_value = ( + self.invest[i, o, p] + * remaining_annuity + * remaining_lifetime + ) * ( + (1 + m.discount_rate) ** (-m.es.periods_years[-1]) + ) + investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -910,6 +928,26 @@ def _objective_expression(self): + self.invest_status[i, o, p] * m.flows[i, o].investment.offset[p] ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + remaining_value = 0 + if lifetime > m.es.periods_matrix[p, -1]: + remaining_lifetime = ( + lifetime - m.es.periods_matrix[p, -1] + ) + remaining_annuity = economics.annuity( + capex=m.flows[i, o].investment.ep_costs[-1], + n=lifetime, + wacc=interest, + ) + remaining_value = ( + self.invest[i, o, p] + * remaining_annuity + * remaining_lifetime + + self.invest_status[i, o, p] + * m.flows[i, o].investment.offset[-1] + ) * ( + (1 + m.discount_rate) ** (-m.es.periods_years[-1]) + ) + investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -926,16 +964,32 @@ def _objective_expression(self): m.es.periods_years[p] + lifetime, ) ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + if lifetime > m.es.periods_matrix[p, -1]: + fixed_costs -= sum( + self.invest[i, o, p] + * m.flows[i, o].investment.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range( + m.es.periods_years[-1], + m.es.periods_years[p] + lifetime, + ) + ) * ( + (1 + m.discount_rate) + ** (-m.es.periods_years[-1]) + ) for i, o in self.EXISTING_INVESTFLOWS: if m.flows[i, o].investment.fixed_costs[0] is not None: lifetime = m.flows[i, o].investment.lifetime age = m.flows[i, o].investment.age + range_limit = max( + m.es.periods_matrix[0, -1], lifetime - age + ) fixed_costs += sum( m.flows[i, o].investment.existing * m.flows[i, o].investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, lifetime - age) + for pp in range(0, range_limit) ) self.investment_costs = Expression(expr=investment_costs) From ca93fb470ae0c6cac11b241d2d090bd274d8b74e Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Mon, 2 Oct 2023 17:15:09 +0200 Subject: [PATCH 013/180] Adjust remaining value and fixed costs for generic storage accordingly --- .../solph/components/_generic_storage.py | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index a10e02ca3..c59a8d1dc 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1735,6 +1735,24 @@ def _objective_expression(self): * lifetime * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) ) + remaining_value = 0 + if lifetime > m.es.periods_matrix[p, -1]: + remaining_lifetime = ( + lifetime - m.es.periods_matrix[p, -1] + ) + remaining_annuity = economics.annuity( + capex=n.investment.ep_costs[-1], + n=lifetime, + wacc=interest, + ) + remaining_value = ( + self.invest[n, p] + * remaining_annuity + * remaining_lifetime + ) * ( + (1 + m.discount_rate) ** (-m.es.periods_years[-1]) + ) + investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -1757,6 +1775,26 @@ def _objective_expression(self): self.invest[n, p] * annuity * lifetime + self.invest_status[n, p] * n.investment.offset[p] ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + remaining_value = 0 + if lifetime > m.es.periods_matrix[p, -1]: + remaining_lifetime = ( + lifetime - m.es.periods_matrix[p, -1] + ) + remaining_annuity = economics.annuity( + capex=n.investment.ep_costs[-1], + n=lifetime, + wacc=interest, + ) + remaining_value = ( + self.invest[n, p] + * remaining_annuity + * remaining_lifetime + + self.invest_status[n, p] + * n.investment.offset[-1] + ) * ( + (1 + m.discount_rate) ** (-m.es.periods_years[-1]) + ) + investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -1773,16 +1811,32 @@ def _objective_expression(self): m.es.periods_years[p] + lifetime, ) ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + if lifetime > m.es.periods_matrix[p, -1]: + fixed_costs -= sum( + self.invest[n, p] + * n.investment.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range( + m.es.periods_years[-1], + m.es.periods_years[p] + lifetime, + ) + ) * ( + (1 + m.discount_rate) + ** (-m.es.periods_years[-1]) + ) for n in self.EXISTING_INVESTSTORAGES: if n.investment.fixed_costs[0] is not None: lifetime = n.investment.lifetime age = n.investment.age + range_limit = max( + m.es.periods_matrix[0, -1], lifetime - age + ) fixed_costs += sum( n.investment.existing * n.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, lifetime - age) + for pp in range(0, range_limit) ) self.investment_costs = Expression(expr=investment_costs) From eb64a516ea9783a16715d99a677428d112e68193 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Mon, 2 Oct 2023 17:24:54 +0200 Subject: [PATCH 014/180] Add bug fix --- src/oemof/solph/components/_generic_storage.py | 2 +- src/oemof/solph/flows/_investment_flow_block.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index c59a8d1dc..b83cff7ef 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1829,7 +1829,7 @@ def _objective_expression(self): if n.investment.fixed_costs[0] is not None: lifetime = n.investment.lifetime age = n.investment.age - range_limit = max( + range_limit = min( m.es.periods_matrix[0, -1], lifetime - age ) fixed_costs += sum( diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 817a9be78..7000786b2 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -982,7 +982,7 @@ def _objective_expression(self): if m.flows[i, o].investment.fixed_costs[0] is not None: lifetime = m.flows[i, o].investment.lifetime age = m.flows[i, o].investment.age - range_limit = max( + range_limit = min( m.es.periods_matrix[0, -1], lifetime - age ) fixed_costs += sum( From 0520abc7ce02a4069c5c92bcfdca99f6313787f6 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Mon, 2 Oct 2023 17:33:19 +0200 Subject: [PATCH 015/180] Include adjustments for SinkDSM investments --- .../components/experimental/_sink_dsm.py | 111 +++++++++++++++++- 1 file changed, 108 insertions(+), 3 deletions(-) diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index eeda335aa..e3e94cf57 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -1344,6 +1344,25 @@ def _objective_expression(self): * lifetime * ((1 + m.discount_rate) ** -m.es.periods_years[p]) ) + remaining_value = 0 + if lifetime > m.es.periods_matrix[p, -1]: + remaining_lifetime = ( + lifetime - m.es.periods_matrix[p, -1] + ) + remaining_annuity = economics.annuity( + capex=g.investment.ep_costs[-1], + n=lifetime, + wacc=interest, + ) + remaining_value = ( + self.invest[g, p] + * remaining_annuity + * remaining_lifetime + ) * ( + (1 + m.discount_rate) + ** (-m.es.periods_years[-1]) + ) + investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[ p @@ -1379,16 +1398,32 @@ def _objective_expression(self): m.es.periods_years[p] + lifetime, ) ) * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + if lifetime > m.es.periods_matrix[p, -1]: + fixed_costs -= sum( + self.invest[g, p] + * g.investment.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range( + m.es.periods_years[-1], + m.es.periods_years[p] + lifetime, + ) + ) * ( + (1 + m.discount_rate) + ** (-m.es.periods_years[-1]) + ) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age + range_limit = min( + m.es.periods_matrix[0, -1], lifetime - age + ) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, lifetime - age) + for pp in range(0, range_limit) ) self.variable_costs = Expression(expr=variable_costs) @@ -3060,6 +3095,25 @@ def _objective_expression(self): * lifetime * ((1 + m.discount_rate) ** -m.es.periods_years[p]) ) + remaining_value = 0 + if lifetime > m.es.periods_matrix[p, -1]: + remaining_lifetime = ( + lifetime - m.es.periods_matrix[p, -1] + ) + remaining_annuity = economics.annuity( + capex=g.investment.ep_costs[-1], + n=lifetime, + wacc=interest, + ) + remaining_value = ( + self.invest[g, p] + * remaining_annuity + * remaining_lifetime + ) * ( + (1 + m.discount_rate) + ** (-m.es.periods_years[-1]) + ) + investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[ p @@ -3099,16 +3153,32 @@ def _objective_expression(self): m.es.periods_years[p] + lifetime, ) ) * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + if lifetime > m.es.periods_matrix[p, -1]: + fixed_costs -= sum( + self.invest[g, p] + * g.investment.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range( + m.es.periods_years[-1], + m.es.periods_years[p] + lifetime, + ) + ) * ( + (1 + m.discount_rate) + ** (-m.es.periods_years[-1]) + ) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age + range_limit = min( + m.es.periods_matrix[0, -1], lifetime - age + ) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, lifetime - age) + for pp in range(0, range_limit) ) self.variable_costs = Expression(expr=variable_costs) @@ -5418,6 +5488,25 @@ def _objective_expression(self): * lifetime * ((1 + m.discount_rate) ** -m.es.periods_years[p]) ) + remaining_value = 0 + if lifetime > m.es.periods_matrix[p, -1]: + remaining_lifetime = ( + lifetime - m.es.periods_matrix[p, -1] + ) + remaining_annuity = economics.annuity( + capex=g.investment.ep_costs[-1], + n=lifetime, + wacc=interest, + ) + remaining_value = ( + self.invest[g, p] + * remaining_annuity + * remaining_lifetime + ) * ( + (1 + m.discount_rate) + ** (-m.es.periods_years[-1]) + ) + investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[ p @@ -5464,16 +5553,32 @@ def _objective_expression(self): m.es.periods_years[p] + lifetime, ) ) * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + if lifetime > m.es.periods_matrix[p, -1]: + fixed_costs -= sum( + self.invest[g, p] + * g.investment.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range( + m.es.periods_years[-1], + m.es.periods_years[p] + lifetime, + ) + ) * ( + (1 + m.discount_rate) + ** (-m.es.periods_years[-1]) + ) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age + range_limit = min( + m.es.periods_matrix[0, -1], lifetime - age + ) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, lifetime - age) + for pp in range(0, range_limit) ) self.variable_costs = Expression(expr=variable_costs) From 6ffe405fd88474bb9a6e6b9e95cbdbf2ddb15926 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 11:31:08 +0200 Subject: [PATCH 016/180] Add getter for period length in years --- src/oemof/solph/_energy_system.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index a2a166fb5..cd633ad23 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -213,6 +213,14 @@ def _extract_periods_matrix(self): periods_matrix.append(row) self.periods_matrix = np.array(periods_matrix) + def get_period_duration(self, period: int): + """Get duration of a period in full years""" + return ( + self.periods[period].max().year + - self.periods[period].min().year + + 1 + ) + def create_time_index( year: int = None, From aa177eb5e4faf1a7cddb0716e30c40cd7cbdb0b6 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 11:31:57 +0200 Subject: [PATCH 017/180] limit present values to optimization horizon and correct erroneous calculation of present values --- .../solph/flows/_investment_flow_block.py | 65 ++++++------------- 1 file changed, 21 insertions(+), 44 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 7000786b2..4db6ba1c2 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -866,6 +866,11 @@ def _objective_expression(self): "microeconomic interest requirements." ) + duration_last_period = m.es.get_period_duration(-1) + end_of_optimization = ( + m.es.periods_years[-1] + duration_last_period + ) + for i, o in self.CONVEX_INVESTFLOWS: lifetime = m.flows[i, o].investment.lifetime interest = m.flows[i, o].investment.interest_rate @@ -881,30 +886,15 @@ def _objective_expression(self): n=lifetime, wacc=interest, ) + duration = min( + end_of_optimization - m.es.periods_years[p], lifetime + ) + present_value_factor = 1 / economics.annuity( + capex=1, n=duration, wacc=m.discount_rate + ) investment_costs_increment = ( - self.invest[i, o, p] - * annuity - * lifetime - * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + self.invest[i, o, p] * annuity * present_value_factor ) - remaining_value = 0 - if lifetime > m.es.periods_matrix[p, -1]: - remaining_lifetime = ( - lifetime - m.es.periods_matrix[p, -1] - ) - remaining_annuity = economics.annuity( - capex=m.flows[i, o].investment.ep_costs[-1], - n=lifetime, - wacc=interest, - ) - remaining_value = ( - self.invest[i, o, p] - * remaining_annuity - * remaining_lifetime - ) * ( - (1 + m.discount_rate) ** (-m.es.periods_years[-1]) - ) - investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -923,31 +913,18 @@ def _objective_expression(self): n=lifetime, wacc=interest, ) + duration = min( + end_of_optimization - m.es.periods_years[p], lifetime + ) + present_value_factor = 1 / economics.annuity( + capex=1, n=duration, wacc=m.discount_rate + ) investment_costs_increment = ( - self.invest[i, o, p] * annuity * lifetime + self.invest[i, o, p] * annuity * present_value_factor + self.invest_status[i, o, p] * m.flows[i, o].investment.offset[p] - ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) - remaining_value = 0 - if lifetime > m.es.periods_matrix[p, -1]: - remaining_lifetime = ( - lifetime - m.es.periods_matrix[p, -1] - ) - remaining_annuity = economics.annuity( - capex=m.flows[i, o].investment.ep_costs[-1], - n=lifetime, - wacc=interest, - ) - remaining_value = ( - self.invest[i, o, p] - * remaining_annuity - * remaining_lifetime - + self.invest_status[i, o, p] - * m.flows[i, o].investment.offset[-1] - ) * ( - (1 + m.discount_rate) ** (-m.es.periods_years[-1]) - ) - investment_costs_increment -= remaining_value + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) + ) investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment From b99f231a4bff5b7e14f878a1259d754e8f97196d Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 13:06:57 +0200 Subject: [PATCH 018/180] Include proper discounting (from start year p) to year 0 --- src/oemof/solph/flows/_investment_flow_block.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 4db6ba1c2..068a10cae 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -867,9 +867,7 @@ def _objective_expression(self): ) duration_last_period = m.es.get_period_duration(-1) - end_of_optimization = ( - m.es.periods_years[-1] + duration_last_period - ) + end_of_optimization = m.es.periods_years[-1] + duration_last_period for i, o in self.CONVEX_INVESTFLOWS: lifetime = m.flows[i, o].investment.lifetime @@ -894,7 +892,7 @@ def _objective_expression(self): ) investment_costs_increment = ( self.invest[i, o, p] * annuity * present_value_factor - ) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -923,8 +921,7 @@ def _objective_expression(self): self.invest[i, o, p] * annuity * present_value_factor + self.invest_status[i, o, p] * m.flows[i, o].investment.offset[p] - * (1 + m.discount_rate) ** (-m.es.periods_years[p]) - ) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment From 6c6f3a0478b41e6ef0d0de9bea4967beea4f58d1 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 13:22:19 +0200 Subject: [PATCH 019/180] Revise / correct fixed costs handling --- .../solph/flows/_investment_flow_block.py | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 068a10cae..1277053e4 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -929,41 +929,32 @@ def _objective_expression(self): if m.flows[i, o].investment.fixed_costs[0] is not None: lifetime = m.flows[i, o].investment.lifetime for p in m.PERIODS: + range_limit = min( + end_of_optimization, + m.es.periods_years[p] + lifetime, + ) fixed_costs += sum( self.invest[i, o, p] * m.flows[i, o].investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) for pp in range( m.es.periods_years[p], - m.es.periods_years[p] + lifetime, + range_limit, ) ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) - if lifetime > m.es.periods_matrix[p, -1]: - fixed_costs -= sum( - self.invest[i, o, p] - * m.flows[i, o].investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) - for pp in range( - m.es.periods_years[-1], - m.es.periods_years[p] + lifetime, - ) - ) * ( - (1 + m.discount_rate) - ** (-m.es.periods_years[-1]) - ) for i, o in self.EXISTING_INVESTFLOWS: if m.flows[i, o].investment.fixed_costs[0] is not None: lifetime = m.flows[i, o].investment.lifetime age = m.flows[i, o].investment.age range_limit = min( - m.es.periods_matrix[0, -1], lifetime - age + end_of_optimization, lifetime - age ) fixed_costs += sum( m.flows[i, o].investment.existing * m.flows[i, o].investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, range_limit) + for pp in range(range_limit) ) self.investment_costs = Expression(expr=investment_costs) From 6f999c0970d28d1fcdf04d66606d04cfb6e21f93 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 13:39:57 +0200 Subject: [PATCH 020/180] Adjust generic storage objective alike --- .../solph/components/_generic_storage.py | 85 ++++++------------- 1 file changed, 25 insertions(+), 60 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index b83cff7ef..dc9424ec2 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1714,6 +1714,9 @@ def _objective_expression(self): "microeconomic interest requirements." ) + duration_last_period = m.es.get_period_duration(-1) + end_of_optimization = m.es.periods_years[-1] + duration_last_period + for n in self.CONVEX_INVESTSTORAGES: lifetime = n.investment.lifetime interest = n.investment.interest_rate @@ -1729,30 +1732,15 @@ def _objective_expression(self): n=lifetime, wacc=interest, ) - investment_costs_increment = ( - self.invest[n, p] - * annuity - * lifetime - * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + duration = min( + end_of_optimization - m.es.periods_years[p], lifetime ) - remaining_value = 0 - if lifetime > m.es.periods_matrix[p, -1]: - remaining_lifetime = ( - lifetime - m.es.periods_matrix[p, -1] - ) - remaining_annuity = economics.annuity( - capex=n.investment.ep_costs[-1], - n=lifetime, - wacc=interest, - ) - remaining_value = ( - self.invest[n, p] - * remaining_annuity - * remaining_lifetime - ) * ( - (1 + m.discount_rate) ** (-m.es.periods_years[-1]) - ) - investment_costs_increment -= remaining_value + present_value_factor = 1 / economics.annuity( + capex=1, n=duration, wacc=m.discount_rate + ) + investment_costs_increment = ( + self.invest[n, p] * annuity * present_value_factor + ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -1771,30 +1759,16 @@ def _objective_expression(self): n=lifetime, wacc=interest, ) + duration = min( + end_of_optimization - m.es.periods_years[p], lifetime + ) + present_value_factor = 1 / economics.annuity( + capex=1, n=duration, wacc=m.discount_rate + ) investment_costs_increment = ( - self.invest[n, p] * annuity * lifetime + self.invest[n, p] * annuity * present_value_factor + self.invest_status[n, p] * n.investment.offset[p] ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) - remaining_value = 0 - if lifetime > m.es.periods_matrix[p, -1]: - remaining_lifetime = ( - lifetime - m.es.periods_matrix[p, -1] - ) - remaining_annuity = economics.annuity( - capex=n.investment.ep_costs[-1], - n=lifetime, - wacc=interest, - ) - remaining_value = ( - self.invest[n, p] - * remaining_annuity - * remaining_lifetime - + self.invest_status[n, p] - * n.investment.offset[-1] - ) * ( - (1 + m.discount_rate) ** (-m.es.periods_years[-1]) - ) - investment_costs_increment -= remaining_value investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -1802,41 +1776,32 @@ def _objective_expression(self): if n.investment.fixed_costs[0] is not None: lifetime = n.investment.lifetime for p in m.PERIODS: + range_limit = min( + end_of_optimization, + m.es.periods_years[p] + lifetime, + ) fixed_costs += sum( self.invest[n, p] * n.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) for pp in range( m.es.periods_years[p], - m.es.periods_years[p] + lifetime, + range_limit, ) ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) - if lifetime > m.es.periods_matrix[p, -1]: - fixed_costs -= sum( - self.invest[n, p] - * n.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) - for pp in range( - m.es.periods_years[-1], - m.es.periods_years[p] + lifetime, - ) - ) * ( - (1 + m.discount_rate) - ** (-m.es.periods_years[-1]) - ) for n in self.EXISTING_INVESTSTORAGES: if n.investment.fixed_costs[0] is not None: lifetime = n.investment.lifetime age = n.investment.age range_limit = min( - m.es.periods_matrix[0, -1], lifetime - age + end_of_optimization, lifetime - age ) fixed_costs += sum( n.investment.existing * n.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, range_limit) + for pp in range(range_limit) ) self.investment_costs = Expression(expr=investment_costs) From f29af6d8a23fe939d9d75149f5c16164a1403b67 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 14:15:59 +0200 Subject: [PATCH 021/180] Adjust Sink DSM objective functions alike --- .../components/experimental/_sink_dsm.py | 210 ++++++------------ 1 file changed, 72 insertions(+), 138 deletions(-) diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index e3e94cf57..bb53bbd74 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -1322,6 +1322,10 @@ def _objective_expression(self): "social planner point of view and does not reflect " "microeconomic interest requirements." ) + + duration_last_period = m.es.get_period_duration(-1) + end_of_optimization = m.es.periods_years[-1] + duration_last_period + for g in self.investdsm: if g.investment.ep_costs is not None: lifetime = g.investment.lifetime @@ -1338,31 +1342,16 @@ def _objective_expression(self): n=lifetime, wacc=interest, ) - investment_costs_increment = ( - self.invest[g, p] - * annuity - * lifetime - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + duration = min( + end_of_optimization - m.es.periods_years[p], + lifetime, ) - remaining_value = 0 - if lifetime > m.es.periods_matrix[p, -1]: - remaining_lifetime = ( - lifetime - m.es.periods_matrix[p, -1] - ) - remaining_annuity = economics.annuity( - capex=g.investment.ep_costs[-1], - n=lifetime, - wacc=interest, - ) - remaining_value = ( - self.invest[g, p] - * remaining_annuity - * remaining_lifetime - ) * ( - (1 + m.discount_rate) - ** (-m.es.periods_years[-1]) - ) - investment_costs_increment -= remaining_value + present_value_factor = 1 / economics.annuity( + capex=1, n=duration, wacc=m.discount_rate + ) + investment_costs_increment = ( + self.invest[g, p] * annuity * present_value_factor + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) investment_costs += investment_costs_increment period_investment_costs[ p @@ -1375,7 +1364,7 @@ def _objective_expression(self): self.dsm_up[g, t] * m.objective_weighting[t] * g.cost_dsm_up[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) variable_costs += ( ( @@ -1383,47 +1372,36 @@ def _objective_expression(self): + self.dsm_do_shed[g, t] * g.cost_dsm_down_shed[t] ) * m.objective_weighting[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime for p in m.PERIODS: + range_limit = min( + end_of_optimization, + m.es.periods_years[p] + lifetime, + ) fixed_costs += sum( self.invest[g, p] * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range( m.es.periods_years[p], - m.es.periods_years[p] + lifetime, - ) - ) * ((1 + m.discount_rate) ** -m.es.periods_years[p]) - if lifetime > m.es.periods_matrix[p, -1]: - fixed_costs -= sum( - self.invest[g, p] - * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) - for pp in range( - m.es.periods_years[-1], - m.es.periods_years[p] + lifetime, - ) - ) * ( - (1 + m.discount_rate) - ** (-m.es.periods_years[-1]) + range_limit, ) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min( - m.es.periods_matrix[0, -1], lifetime - age - ) + range_limit = min(end_of_optimization, lifetime - age) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, range_limit) + * (1 + m.discount_rate) ** (-pp) + for pp in range(range_limit) ) self.variable_costs = Expression(expr=variable_costs) @@ -3073,6 +3051,10 @@ def _objective_expression(self): "social planner point of view and does not reflect " "microeconomic interest requirements." ) + + duration_last_period = m.es.get_period_duration(-1) + end_of_optimization = m.es.periods_years[-1] + duration_last_period + for g in self.investdsm: if g.investment.ep_costs is not None: lifetime = g.investment.lifetime @@ -3089,31 +3071,16 @@ def _objective_expression(self): n=lifetime, wacc=interest, ) - investment_costs_increment = ( - self.invest[g, p] - * annuity - * lifetime - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + duration = min( + end_of_optimization - m.es.periods_years[p], + lifetime, ) - remaining_value = 0 - if lifetime > m.es.periods_matrix[p, -1]: - remaining_lifetime = ( - lifetime - m.es.periods_matrix[p, -1] - ) - remaining_annuity = economics.annuity( - capex=g.investment.ep_costs[-1], - n=lifetime, - wacc=interest, - ) - remaining_value = ( - self.invest[g, p] - * remaining_annuity - * remaining_lifetime - ) * ( - (1 + m.discount_rate) - ** (-m.es.periods_years[-1]) - ) - investment_costs_increment -= remaining_value + present_value_factor = 1 / economics.annuity( + capex=1, n=duration, wacc=m.discount_rate + ) + investment_costs_increment = ( + self.invest[g, p] * annuity * present_value_factor + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) investment_costs += investment_costs_increment period_investment_costs[ p @@ -3126,7 +3093,7 @@ def _objective_expression(self): self.dsm_up[g, t] * m.objective_weighting[t] * g.cost_dsm_up[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) variable_costs += ( ( @@ -3138,47 +3105,36 @@ def _objective_expression(self): + self.dsm_do_shed[g, t] * g.cost_dsm_down_shed[t] ) * m.objective_weighting[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime for p in m.PERIODS: + range_limit = min( + end_of_optimization, + m.es.periods_years[p] + lifetime, + ) fixed_costs += sum( self.invest[g, p] * g.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) for pp in range( m.es.periods_years[p], - m.es.periods_years[p] + lifetime, - ) - ) * ((1 + m.discount_rate) ** -m.es.periods_years[p]) - if lifetime > m.es.periods_matrix[p, -1]: - fixed_costs -= sum( - self.invest[g, p] - * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) - for pp in range( - m.es.periods_years[-1], - m.es.periods_years[p] + lifetime, - ) - ) * ( - (1 + m.discount_rate) - ** (-m.es.periods_years[-1]) + range_limit, ) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min( - m.es.periods_matrix[0, -1], lifetime - age - ) + range_limit = min(end_of_optimization, lifetime - age) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, range_limit) + * (1 + m.discount_rate) ** (-pp) + for pp in range(range_limit) ) self.variable_costs = Expression(expr=variable_costs) @@ -5466,6 +5422,10 @@ def _objective_expression(self): "social planner point of view and does not reflect " "microeconomic interest requirements." ) + + duration_last_period = m.es.get_period_duration(-1) + end_of_optimization = m.es.periods_years[-1] + duration_last_period + for g in self.INVESTDR: if g.investment.ep_costs is not None: lifetime = g.investment.lifetime @@ -5482,31 +5442,16 @@ def _objective_expression(self): n=lifetime, wacc=interest, ) - investment_costs_increment = ( - self.invest[g, p] - * annuity - * lifetime - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + duration = min( + end_of_optimization - m.es.periods_years[p], + lifetime, ) - remaining_value = 0 - if lifetime > m.es.periods_matrix[p, -1]: - remaining_lifetime = ( - lifetime - m.es.periods_matrix[p, -1] - ) - remaining_annuity = economics.annuity( - capex=g.investment.ep_costs[-1], - n=lifetime, - wacc=interest, - ) - remaining_value = ( - self.invest[g, p] - * remaining_annuity - * remaining_lifetime - ) * ( - (1 + m.discount_rate) - ** (-m.es.periods_years[-1]) - ) - investment_costs_increment -= remaining_value + present_value_factor = 1 / economics.annuity( + capex=1, n=duration, wacc=m.discount_rate + ) + investment_costs_increment = ( + self.invest[g, p] * annuity * present_value_factor + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) investment_costs += investment_costs_increment period_investment_costs[ p @@ -5525,7 +5470,7 @@ def _objective_expression(self): * g.cost_dsm_up[t] ) * m.objective_weighting[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) variable_costs += ( ( @@ -5538,47 +5483,36 @@ def _objective_expression(self): + self.dsm_do_shed[g, t] * g.cost_dsm_down_shed[t] ) * m.objective_weighting[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime for p in m.PERIODS: + range_limit = min( + end_of_optimization, + m.es.periods_years[p] + lifetime, + ) fixed_costs += sum( self.invest[g, p] * g.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) for pp in range( m.es.periods_years[p], - m.es.periods_years[p] + lifetime, - ) - ) * ((1 + m.discount_rate) ** -m.es.periods_years[p]) - if lifetime > m.es.periods_matrix[p, -1]: - fixed_costs -= sum( - self.invest[g, p] - * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) - for pp in range( - m.es.periods_years[-1], - m.es.periods_years[p] + lifetime, - ) - ) * ( - (1 + m.discount_rate) - ** (-m.es.periods_years[-1]) + range_limit, ) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min( - m.es.periods_matrix[0, -1], lifetime - age - ) + range_limit = min(end_of_optimization, lifetime - age) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, range_limit) + for pp in range(range_limit) ) self.variable_costs = Expression(expr=variable_costs) From bbe4d04edf93781ff4c5d1d9bfa3d5ba0ccfb98d Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 14:16:09 +0200 Subject: [PATCH 022/180] Revise formatting --- src/oemof/solph/components/_generic_storage.py | 14 ++++++-------- src/oemof/solph/flows/_investment_flow_block.py | 10 ++++------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index dc9424ec2..04e86198c 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1740,7 +1740,7 @@ def _objective_expression(self): ) investment_costs_increment = ( self.invest[n, p] * annuity * present_value_factor - ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -1768,7 +1768,7 @@ def _objective_expression(self): investment_costs_increment = ( self.invest[n, p] * annuity * present_value_factor + self.invest_status[n, p] * n.investment.offset[p] - ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) investment_costs += investment_costs_increment period_investment_costs[p] += investment_costs_increment @@ -1783,24 +1783,22 @@ def _objective_expression(self): fixed_costs += sum( self.invest[n, p] * n.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range( m.es.periods_years[p], range_limit, ) - ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) for n in self.EXISTING_INVESTSTORAGES: if n.investment.fixed_costs[0] is not None: lifetime = n.investment.lifetime age = n.investment.age - range_limit = min( - end_of_optimization, lifetime - age - ) + range_limit = min(end_of_optimization, lifetime - age) fixed_costs += sum( n.investment.existing * n.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range(range_limit) ) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 1277053e4..c6c05e224 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -936,24 +936,22 @@ def _objective_expression(self): fixed_costs += sum( self.invest[i, o, p] * m.flows[i, o].investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range( m.es.periods_years[p], range_limit, ) - ) * ((1 + m.discount_rate) ** (-m.es.periods_years[p])) + ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) for i, o in self.EXISTING_INVESTFLOWS: if m.flows[i, o].investment.fixed_costs[0] is not None: lifetime = m.flows[i, o].investment.lifetime age = m.flows[i, o].investment.age - range_limit = min( - end_of_optimization, lifetime - age - ) + range_limit = min(end_of_optimization, lifetime - age) fixed_costs += sum( m.flows[i, o].investment.existing * m.flows[i, o].investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range(range_limit) ) From dad4616997fe4cf810666732a957e53be31b6a28 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 14:35:03 +0200 Subject: [PATCH 023/180] Stick to numpydoc code style --- src/oemof/solph/_energy_system.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index cd633ad23..3d40fafe0 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -213,8 +213,19 @@ def _extract_periods_matrix(self): periods_matrix.append(row) self.periods_matrix = np.array(periods_matrix) - def get_period_duration(self, period: int): - """Get duration of a period in full years""" + def get_period_duration(self, period): + """Get duration of a period in full years + + Parameters + ---------- + period : int + Period for which the duration in years shall be obtained + + Returns + ------- + int + Duration of the period + """ return ( self.periods[period].max().year - self.periods[period].min().year From 7400c9c11eb13559f76aded77d5eb55990cb2c97 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 15:43:10 +0200 Subject: [PATCH 024/180] Adjust lp files to changes --- .../connect_investment_multi_period.lp | 294 +++++++++--------- .../lp_files/converter_invest_multi_period.lp | 162 +++++----- ...erter_invest_with_existing_multi_period.lp | 162 +++++----- .../dsm_module_DIW_invest_multi_period.lp | 8 +- .../dsm_module_DLR_invest_multi_period.lp | 12 +- .../dsm_module_oemof_invest_multi_period.lp | 8 +- .../fixed_source_invest_sink_multi_period.lp | 6 +- .../flow_invest_with_offset_multi_period.lp | 6 +- ...est_with_offset_no_minimum_multi_period.lp | 6 +- ...flow_invest_without_offset_multi_period.lp | 6 +- .../invest_source_fixed_sink_multi_period.lp | 6 +- ...inear_converter_chp_invest_multi_period.lp | 66 ++-- .../linear_converter_invest_multi_period.lp | 54 ++-- ...inear_converter_invest_multi_period_old.lp | 54 ++-- tests/lp_files/multi_period_period_length.lp | 104 +++---- tests/lp_files/periodical_investment_limit.lp | 230 +++++++------- ...eriodical_investment_limit_with_dsm_DIW.lp | 24 +- ...eriodical_investment_limit_with_dsm_DLR.lp | 24 +- ...iodical_investment_limit_with_dsm_oemof.lp | 24 +- .../lp_files/storage_invest_1_multi_period.lp | 176 +++++------ .../lp_files/storage_invest_2_multi_period.lp | 188 +++++------ .../lp_files/storage_invest_3_multi_period.lp | 12 +- .../lp_files/storage_invest_4_multi_period.lp | 6 +- .../lp_files/storage_invest_5_multi_period.lp | 178 +++++------ .../lp_files/storage_invest_6_multi_period.lp | 12 +- ...orage_invest_all_nonconvex_multi_period.lp | 248 +++++++-------- .../storage_invest_minimum_multi_period.lp | 6 +- tests/lp_files/storage_invest_multi_period.lp | 6 +- ...storage_invest_with_offset_multi_period.lp | 176 +++++------ ...rage_invest_without_offset_multi_period.lp | 176 +++++------ 30 files changed, 1220 insertions(+), 1220 deletions(-) diff --git a/tests/lp_files/connect_investment_multi_period.lp b/tests/lp_files/connect_investment_multi_period.lp index cc22c48bc..75e8a280e 100644 --- a/tests/lp_files/connect_investment_multi_period.lp +++ b/tests/lp_files/connect_investment_multi_period.lp @@ -2,21 +2,21 @@ min objective: -+127.95247418638057 InvestmentFlowBlock_invest(Source_Bus1_0) -+125.44360214351036 InvestmentFlowBlock_invest(Source_Bus1_1) -+122.9839236701082 InvestmentFlowBlock_invest(Source_Bus1_2) -+520.1320088877258 InvestmentFlowBlock_invest(Bus1_Sink_0) -+509.93334204678996 InvestmentFlowBlock_invest(Bus1_Sink_1) -+499.9346490654803 InvestmentFlowBlock_invest(Bus1_Sink_2) -+150.83828257744048 GenericInvestmentStorageBlock_invest(storage_0) -+147.8806691935691 GenericInvestmentStorageBlock_invest(storage_1) -+144.9810482289893 GenericInvestmentStorageBlock_invest(storage_2) ++499.99999999999994 InvestmentFlowBlock_invest(Bus1_Sink_0) ++330.02221931773533 InvestmentFlowBlock_invest(Bus1_Sink_1) ++163.37733629590875 InvestmentFlowBlock_invest(Bus1_Sink_2) ++123.0 InvestmentFlowBlock_invest(Source_Bus1_0) ++81.1854659521629 InvestmentFlowBlock_invest(Source_Bus1_1) ++40.19082472879356 InvestmentFlowBlock_invest(Source_Bus1_2) ++144.99999999999997 GenericInvestmentStorageBlock_invest(storage_0) ++95.70644360214325 GenericInvestmentStorageBlock_invest(storage_1) ++47.37942752581354 GenericInvestmentStorageBlock_invest(storage_2) s.t. c_e__equate_InvestmentFlowBlock_invest(Source_Bus1_0)_InvestmentFlowBlock_invest(Bus1_Sink_0)__: -+2 InvestmentFlowBlock_invest(Source_Bus1_0) -1 InvestmentFlowBlock_invest(Bus1_Sink_0) ++2 InvestmentFlowBlock_invest(Source_Bus1_0) = 0 c_e__equate_InvestmentFlowBlock_invest(Source_Bus1_0)_GenericInvestmentStorageBlock_invest(storage_0)__: @@ -66,23 +66,23 @@ c_e_BusBlock_balance(Bus1_2_5)_: -1 flow(Bus1_Sink_2_5) = 0 -c_e_InvestmentFlowBlock_total_rule(Source_Bus1_0)_: --1 InvestmentFlowBlock_invest(Source_Bus1_0) -+1 InvestmentFlowBlock_total(Source_Bus1_0) +c_e_InvestmentFlowBlock_total_rule(Bus1_Sink_0)_: +-1 InvestmentFlowBlock_invest(Bus1_Sink_0) ++1 InvestmentFlowBlock_total(Bus1_Sink_0) = 0 -c_e_InvestmentFlowBlock_total_rule(Source_Bus1_1)_: --1 InvestmentFlowBlock_invest(Source_Bus1_1) --1 InvestmentFlowBlock_total(Source_Bus1_0) -+1 InvestmentFlowBlock_total(Source_Bus1_1) -+1 InvestmentFlowBlock_old(Source_Bus1_1) +c_e_InvestmentFlowBlock_total_rule(Bus1_Sink_1)_: +-1 InvestmentFlowBlock_invest(Bus1_Sink_1) +-1 InvestmentFlowBlock_total(Bus1_Sink_0) ++1 InvestmentFlowBlock_total(Bus1_Sink_1) ++1 InvestmentFlowBlock_old(Bus1_Sink_1) = 0 -c_e_InvestmentFlowBlock_total_rule(Source_Bus1_2)_: --1 InvestmentFlowBlock_invest(Source_Bus1_2) --1 InvestmentFlowBlock_total(Source_Bus1_1) -+1 InvestmentFlowBlock_total(Source_Bus1_2) -+1 InvestmentFlowBlock_old(Source_Bus1_2) +c_e_InvestmentFlowBlock_total_rule(Bus1_Sink_2)_: +-1 InvestmentFlowBlock_invest(Bus1_Sink_2) +-1 InvestmentFlowBlock_total(Bus1_Sink_1) ++1 InvestmentFlowBlock_total(Bus1_Sink_2) ++1 InvestmentFlowBlock_old(Bus1_Sink_2) = 0 c_e_InvestmentFlowBlock_total_rule(Bus1_storage_0)_: @@ -104,23 +104,23 @@ c_e_InvestmentFlowBlock_total_rule(Bus1_storage_2)_: +1 InvestmentFlowBlock_old(Bus1_storage_2) = 0 -c_e_InvestmentFlowBlock_total_rule(Bus1_Sink_0)_: --1 InvestmentFlowBlock_invest(Bus1_Sink_0) -+1 InvestmentFlowBlock_total(Bus1_Sink_0) +c_e_InvestmentFlowBlock_total_rule(Source_Bus1_0)_: +-1 InvestmentFlowBlock_invest(Source_Bus1_0) ++1 InvestmentFlowBlock_total(Source_Bus1_0) = 0 -c_e_InvestmentFlowBlock_total_rule(Bus1_Sink_1)_: --1 InvestmentFlowBlock_invest(Bus1_Sink_1) --1 InvestmentFlowBlock_total(Bus1_Sink_0) -+1 InvestmentFlowBlock_total(Bus1_Sink_1) -+1 InvestmentFlowBlock_old(Bus1_Sink_1) +c_e_InvestmentFlowBlock_total_rule(Source_Bus1_1)_: +-1 InvestmentFlowBlock_invest(Source_Bus1_1) +-1 InvestmentFlowBlock_total(Source_Bus1_0) ++1 InvestmentFlowBlock_total(Source_Bus1_1) ++1 InvestmentFlowBlock_old(Source_Bus1_1) = 0 -c_e_InvestmentFlowBlock_total_rule(Bus1_Sink_2)_: --1 InvestmentFlowBlock_invest(Bus1_Sink_2) --1 InvestmentFlowBlock_total(Bus1_Sink_1) -+1 InvestmentFlowBlock_total(Bus1_Sink_2) -+1 InvestmentFlowBlock_old(Bus1_Sink_2) +c_e_InvestmentFlowBlock_total_rule(Source_Bus1_2)_: +-1 InvestmentFlowBlock_invest(Source_Bus1_2) +-1 InvestmentFlowBlock_total(Source_Bus1_1) ++1 InvestmentFlowBlock_total(Source_Bus1_2) ++1 InvestmentFlowBlock_old(Source_Bus1_2) = 0 c_e_InvestmentFlowBlock_total_rule(storage_Bus1_0)_: @@ -142,16 +142,16 @@ c_e_InvestmentFlowBlock_total_rule(storage_Bus1_2)_: +1 InvestmentFlowBlock_old(storage_Bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_0)_: -+1 InvestmentFlowBlock_old_end(Source_Bus1_0) +c_e_InvestmentFlowBlock_old_rule_end(Bus1_Sink_0)_: ++1 InvestmentFlowBlock_old_end(Bus1_Sink_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_1)_: -+1 InvestmentFlowBlock_old_end(Source_Bus1_1) +c_e_InvestmentFlowBlock_old_rule_end(Bus1_Sink_1)_: ++1 InvestmentFlowBlock_old_end(Bus1_Sink_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_2)_: -+1 InvestmentFlowBlock_old_end(Source_Bus1_2) +c_e_InvestmentFlowBlock_old_rule_end(Bus1_Sink_2)_: ++1 InvestmentFlowBlock_old_end(Bus1_Sink_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(Bus1_storage_0)_: @@ -166,16 +166,16 @@ c_e_InvestmentFlowBlock_old_rule_end(Bus1_storage_2)_: +1 InvestmentFlowBlock_old_end(Bus1_storage_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Bus1_Sink_0)_: -+1 InvestmentFlowBlock_old_end(Bus1_Sink_0) +c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_0)_: ++1 InvestmentFlowBlock_old_end(Source_Bus1_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Bus1_Sink_1)_: -+1 InvestmentFlowBlock_old_end(Bus1_Sink_1) +c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_1)_: ++1 InvestmentFlowBlock_old_end(Source_Bus1_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Bus1_Sink_2)_: -+1 InvestmentFlowBlock_old_end(Bus1_Sink_2) +c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_2)_: ++1 InvestmentFlowBlock_old_end(Source_Bus1_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(storage_Bus1_0)_: @@ -190,16 +190,16 @@ c_e_InvestmentFlowBlock_old_rule_end(storage_Bus1_2)_: +1 InvestmentFlowBlock_old_end(storage_Bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_0)_: -+1 InvestmentFlowBlock_old_exo(Source_Bus1_0) +c_e_InvestmentFlowBlock_old_rule_exo(Bus1_Sink_0)_: ++1 InvestmentFlowBlock_old_exo(Bus1_Sink_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_1)_: -+1 InvestmentFlowBlock_old_exo(Source_Bus1_1) +c_e_InvestmentFlowBlock_old_rule_exo(Bus1_Sink_1)_: ++1 InvestmentFlowBlock_old_exo(Bus1_Sink_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_2)_: -+1 InvestmentFlowBlock_old_exo(Source_Bus1_2) +c_e_InvestmentFlowBlock_old_rule_exo(Bus1_Sink_2)_: ++1 InvestmentFlowBlock_old_exo(Bus1_Sink_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(Bus1_storage_0)_: @@ -214,16 +214,16 @@ c_e_InvestmentFlowBlock_old_rule_exo(Bus1_storage_2)_: +1 InvestmentFlowBlock_old_exo(Bus1_storage_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Bus1_Sink_0)_: -+1 InvestmentFlowBlock_old_exo(Bus1_Sink_0) +c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_0)_: ++1 InvestmentFlowBlock_old_exo(Source_Bus1_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Bus1_Sink_1)_: -+1 InvestmentFlowBlock_old_exo(Bus1_Sink_1) +c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_1)_: ++1 InvestmentFlowBlock_old_exo(Source_Bus1_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Bus1_Sink_2)_: -+1 InvestmentFlowBlock_old_exo(Bus1_Sink_2) +c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_2)_: ++1 InvestmentFlowBlock_old_exo(Source_Bus1_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(storage_Bus1_0)_: @@ -238,22 +238,22 @@ c_e_InvestmentFlowBlock_old_rule_exo(storage_Bus1_2)_: +1 InvestmentFlowBlock_old_exo(storage_Bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule(Source_Bus1_0)_: --1 InvestmentFlowBlock_old_end(Source_Bus1_0) --1 InvestmentFlowBlock_old_exo(Source_Bus1_0) -+1 InvestmentFlowBlock_old(Source_Bus1_0) +c_e_InvestmentFlowBlock_old_rule(Bus1_Sink_0)_: +-1 InvestmentFlowBlock_old_end(Bus1_Sink_0) +-1 InvestmentFlowBlock_old_exo(Bus1_Sink_0) ++1 InvestmentFlowBlock_old(Bus1_Sink_0) = 0 -c_e_InvestmentFlowBlock_old_rule(Source_Bus1_1)_: -+1 InvestmentFlowBlock_old(Source_Bus1_1) --1 InvestmentFlowBlock_old_end(Source_Bus1_1) --1 InvestmentFlowBlock_old_exo(Source_Bus1_1) +c_e_InvestmentFlowBlock_old_rule(Bus1_Sink_1)_: ++1 InvestmentFlowBlock_old(Bus1_Sink_1) +-1 InvestmentFlowBlock_old_end(Bus1_Sink_1) +-1 InvestmentFlowBlock_old_exo(Bus1_Sink_1) = 0 -c_e_InvestmentFlowBlock_old_rule(Source_Bus1_2)_: -+1 InvestmentFlowBlock_old(Source_Bus1_2) --1 InvestmentFlowBlock_old_end(Source_Bus1_2) --1 InvestmentFlowBlock_old_exo(Source_Bus1_2) +c_e_InvestmentFlowBlock_old_rule(Bus1_Sink_2)_: ++1 InvestmentFlowBlock_old(Bus1_Sink_2) +-1 InvestmentFlowBlock_old_end(Bus1_Sink_2) +-1 InvestmentFlowBlock_old_exo(Bus1_Sink_2) = 0 c_e_InvestmentFlowBlock_old_rule(Bus1_storage_0)_: @@ -274,22 +274,22 @@ c_e_InvestmentFlowBlock_old_rule(Bus1_storage_2)_: -1 InvestmentFlowBlock_old_exo(Bus1_storage_2) = 0 -c_e_InvestmentFlowBlock_old_rule(Bus1_Sink_0)_: --1 InvestmentFlowBlock_old_end(Bus1_Sink_0) --1 InvestmentFlowBlock_old_exo(Bus1_Sink_0) -+1 InvestmentFlowBlock_old(Bus1_Sink_0) +c_e_InvestmentFlowBlock_old_rule(Source_Bus1_0)_: +-1 InvestmentFlowBlock_old_end(Source_Bus1_0) +-1 InvestmentFlowBlock_old_exo(Source_Bus1_0) ++1 InvestmentFlowBlock_old(Source_Bus1_0) = 0 -c_e_InvestmentFlowBlock_old_rule(Bus1_Sink_1)_: -+1 InvestmentFlowBlock_old(Bus1_Sink_1) --1 InvestmentFlowBlock_old_end(Bus1_Sink_1) --1 InvestmentFlowBlock_old_exo(Bus1_Sink_1) +c_e_InvestmentFlowBlock_old_rule(Source_Bus1_1)_: ++1 InvestmentFlowBlock_old(Source_Bus1_1) +-1 InvestmentFlowBlock_old_end(Source_Bus1_1) +-1 InvestmentFlowBlock_old_exo(Source_Bus1_1) = 0 -c_e_InvestmentFlowBlock_old_rule(Bus1_Sink_2)_: -+1 InvestmentFlowBlock_old(Bus1_Sink_2) --1 InvestmentFlowBlock_old_end(Bus1_Sink_2) --1 InvestmentFlowBlock_old_exo(Bus1_Sink_2) +c_e_InvestmentFlowBlock_old_rule(Source_Bus1_2)_: ++1 InvestmentFlowBlock_old(Source_Bus1_2) +-1 InvestmentFlowBlock_old_end(Source_Bus1_2) +-1 InvestmentFlowBlock_old_exo(Source_Bus1_2) = 0 c_e_InvestmentFlowBlock_old_rule(storage_Bus1_0)_: @@ -310,34 +310,34 @@ c_e_InvestmentFlowBlock_old_rule(storage_Bus1_2)_: -1 InvestmentFlowBlock_old_exo(storage_Bus1_2) = 0 -c_u_InvestmentFlowBlock_max(Source_Bus1_0_0)_: -+1 flow(Source_Bus1_0_0) --1 InvestmentFlowBlock_total(Source_Bus1_0) +c_u_InvestmentFlowBlock_max(Bus1_Sink_0_0)_: ++1 flow(Bus1_Sink_0_0) +-1 InvestmentFlowBlock_total(Bus1_Sink_0) <= 0 -c_u_InvestmentFlowBlock_max(Source_Bus1_0_1)_: -+1 flow(Source_Bus1_0_1) --1 InvestmentFlowBlock_total(Source_Bus1_0) +c_u_InvestmentFlowBlock_max(Bus1_Sink_0_1)_: ++1 flow(Bus1_Sink_0_1) +-1 InvestmentFlowBlock_total(Bus1_Sink_0) <= 0 -c_u_InvestmentFlowBlock_max(Source_Bus1_1_2)_: -+1 flow(Source_Bus1_1_2) --1 InvestmentFlowBlock_total(Source_Bus1_1) +c_u_InvestmentFlowBlock_max(Bus1_Sink_1_2)_: ++1 flow(Bus1_Sink_1_2) +-1 InvestmentFlowBlock_total(Bus1_Sink_1) <= 0 -c_u_InvestmentFlowBlock_max(Source_Bus1_1_3)_: -+1 flow(Source_Bus1_1_3) --1 InvestmentFlowBlock_total(Source_Bus1_1) +c_u_InvestmentFlowBlock_max(Bus1_Sink_1_3)_: ++1 flow(Bus1_Sink_1_3) +-1 InvestmentFlowBlock_total(Bus1_Sink_1) <= 0 -c_u_InvestmentFlowBlock_max(Source_Bus1_2_4)_: -+1 flow(Source_Bus1_2_4) --1 InvestmentFlowBlock_total(Source_Bus1_2) +c_u_InvestmentFlowBlock_max(Bus1_Sink_2_4)_: ++1 flow(Bus1_Sink_2_4) +-1 InvestmentFlowBlock_total(Bus1_Sink_2) <= 0 -c_u_InvestmentFlowBlock_max(Source_Bus1_2_5)_: -+1 flow(Source_Bus1_2_5) --1 InvestmentFlowBlock_total(Source_Bus1_2) +c_u_InvestmentFlowBlock_max(Bus1_Sink_2_5)_: ++1 flow(Bus1_Sink_2_5) +-1 InvestmentFlowBlock_total(Bus1_Sink_2) <= 0 c_u_InvestmentFlowBlock_max(Bus1_storage_0_0)_: @@ -370,34 +370,34 @@ c_u_InvestmentFlowBlock_max(Bus1_storage_2_5)_: -1 InvestmentFlowBlock_total(Bus1_storage_2) <= 0 -c_u_InvestmentFlowBlock_max(Bus1_Sink_0_0)_: -+1 flow(Bus1_Sink_0_0) --1 InvestmentFlowBlock_total(Bus1_Sink_0) +c_u_InvestmentFlowBlock_max(Source_Bus1_0_0)_: ++1 flow(Source_Bus1_0_0) +-1 InvestmentFlowBlock_total(Source_Bus1_0) <= 0 -c_u_InvestmentFlowBlock_max(Bus1_Sink_0_1)_: -+1 flow(Bus1_Sink_0_1) --1 InvestmentFlowBlock_total(Bus1_Sink_0) +c_u_InvestmentFlowBlock_max(Source_Bus1_0_1)_: ++1 flow(Source_Bus1_0_1) +-1 InvestmentFlowBlock_total(Source_Bus1_0) <= 0 -c_u_InvestmentFlowBlock_max(Bus1_Sink_1_2)_: -+1 flow(Bus1_Sink_1_2) --1 InvestmentFlowBlock_total(Bus1_Sink_1) +c_u_InvestmentFlowBlock_max(Source_Bus1_1_2)_: ++1 flow(Source_Bus1_1_2) +-1 InvestmentFlowBlock_total(Source_Bus1_1) <= 0 -c_u_InvestmentFlowBlock_max(Bus1_Sink_1_3)_: -+1 flow(Bus1_Sink_1_3) --1 InvestmentFlowBlock_total(Bus1_Sink_1) +c_u_InvestmentFlowBlock_max(Source_Bus1_1_3)_: ++1 flow(Source_Bus1_1_3) +-1 InvestmentFlowBlock_total(Source_Bus1_1) <= 0 -c_u_InvestmentFlowBlock_max(Bus1_Sink_2_4)_: -+1 flow(Bus1_Sink_2_4) --1 InvestmentFlowBlock_total(Bus1_Sink_2) +c_u_InvestmentFlowBlock_max(Source_Bus1_2_4)_: ++1 flow(Source_Bus1_2_4) +-1 InvestmentFlowBlock_total(Source_Bus1_2) <= 0 -c_u_InvestmentFlowBlock_max(Bus1_Sink_2_5)_: -+1 flow(Bus1_Sink_2_5) --1 InvestmentFlowBlock_total(Bus1_Sink_2) +c_u_InvestmentFlowBlock_max(Source_Bus1_2_5)_: ++1 flow(Source_Bus1_2_5) +-1 InvestmentFlowBlock_total(Source_Bus1_2) <= 0 c_u_InvestmentFlowBlock_max(storage_Bus1_0_0)_: @@ -591,12 +591,12 @@ c_u_GenericInvestmentStorageBlock_max_storage_content(storage_2_5)_: <= 0 bounds - 0 <= InvestmentFlowBlock_invest(Source_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_invest(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_invest(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_invest(Bus1_Sink_0) <= +inf 0 <= InvestmentFlowBlock_invest(Bus1_Sink_1) <= +inf 0 <= InvestmentFlowBlock_invest(Bus1_Sink_2) <= +inf + 0 <= InvestmentFlowBlock_invest(Source_Bus1_0) <= +inf + 0 <= InvestmentFlowBlock_invest(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_invest(Source_Bus1_2) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage_0) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage_1) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage_2) <= +inf @@ -624,11 +624,11 @@ bounds 0 <= flow(Source_Bus1_2_5) <= +inf 0 <= flow(Bus1_storage_2_5) <= +inf 0 <= flow(Bus1_Sink_2_5) <= +inf - 0 <= InvestmentFlowBlock_total(Source_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_total(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_old(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_total(Source_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old(Source_Bus1_2) <= +inf + 0 <= InvestmentFlowBlock_total(Bus1_Sink_0) <= +inf + 0 <= InvestmentFlowBlock_total(Bus1_Sink_1) <= +inf + 0 <= InvestmentFlowBlock_old(Bus1_Sink_1) <= +inf + 0 <= InvestmentFlowBlock_total(Bus1_Sink_2) <= +inf + 0 <= InvestmentFlowBlock_old(Bus1_Sink_2) <= +inf 0 <= InvestmentFlowBlock_total(Bus1_storage_0) <= +inf 0 <= InvestmentFlowBlock_invest(Bus1_storage_0) <= +inf 0 <= InvestmentFlowBlock_total(Bus1_storage_1) <= +inf @@ -637,11 +637,11 @@ bounds 0 <= InvestmentFlowBlock_total(Bus1_storage_2) <= +inf 0 <= InvestmentFlowBlock_invest(Bus1_storage_2) <= +inf 0 <= InvestmentFlowBlock_old(Bus1_storage_2) <= +inf - 0 <= InvestmentFlowBlock_total(Bus1_Sink_0) <= +inf - 0 <= InvestmentFlowBlock_total(Bus1_Sink_1) <= +inf - 0 <= InvestmentFlowBlock_old(Bus1_Sink_1) <= +inf - 0 <= InvestmentFlowBlock_total(Bus1_Sink_2) <= +inf - 0 <= InvestmentFlowBlock_old(Bus1_Sink_2) <= +inf + 0 <= InvestmentFlowBlock_total(Source_Bus1_0) <= +inf + 0 <= InvestmentFlowBlock_total(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_old(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_total(Source_Bus1_2) <= +inf + 0 <= InvestmentFlowBlock_old(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_total(storage_Bus1_0) <= +inf 0 <= InvestmentFlowBlock_invest(storage_Bus1_0) <= +inf 0 <= InvestmentFlowBlock_total(storage_Bus1_1) <= +inf @@ -650,33 +650,33 @@ bounds 0 <= InvestmentFlowBlock_total(storage_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_invest(storage_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old(storage_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(Source_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(Source_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(Bus1_storage_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(Bus1_storage_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(Bus1_storage_2) <= +inf 0 <= InvestmentFlowBlock_old_end(Bus1_Sink_0) <= +inf 0 <= InvestmentFlowBlock_old_end(Bus1_Sink_1) <= +inf 0 <= InvestmentFlowBlock_old_end(Bus1_Sink_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(Bus1_storage_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(Bus1_storage_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(Bus1_storage_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(Source_Bus1_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_Bus1_0) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_Bus1_1) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(Bus1_Sink_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(Bus1_Sink_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(Bus1_Sink_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_Bus1_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_Bus1_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old(Source_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_old(Bus1_storage_0) <= +inf 0 <= InvestmentFlowBlock_old(Bus1_Sink_0) <= +inf + 0 <= InvestmentFlowBlock_old(Bus1_storage_0) <= +inf + 0 <= InvestmentFlowBlock_old(Source_Bus1_0) <= +inf 0 <= InvestmentFlowBlock_old(storage_Bus1_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_1) <= +inf diff --git a/tests/lp_files/converter_invest_multi_period.lp b/tests/lp_files/converter_invest_multi_period.lp index 38337e8ac..1ac09ba27 100644 --- a/tests/lp_files/converter_invest_multi_period.lp +++ b/tests/lp_files/converter_invest_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+24.462687250116133 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) -+23.98302671580013 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_1) -+23.512771290000128 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_2) ++3.5273767282312036 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) ++2.328225392441188 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_1) ++1.1525868279411837 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_2) +50 flow(powerplant_gas_coal_electricityBus_0_0) +50 flow(powerplant_gas_coal_electricityBus_0_1) +49.01960784313725 flow(powerplant_gas_coal_electricityBus_1_2) @@ -20,28 +20,28 @@ objective: s.t. -c_e_BusBlock_balance(coalBus_0_0)_: -+1 flow(coalBus_powerplant_gas_coal_0_0) +c_e_BusBlock_balance(electricityBus_0_0)_: ++1 flow(powerplant_gas_coal_electricityBus_0_0) = 0 -c_e_BusBlock_balance(coalBus_0_1)_: -+1 flow(coalBus_powerplant_gas_coal_0_1) +c_e_BusBlock_balance(electricityBus_0_1)_: ++1 flow(powerplant_gas_coal_electricityBus_0_1) = 0 -c_e_BusBlock_balance(coalBus_1_2)_: -+1 flow(coalBus_powerplant_gas_coal_1_2) +c_e_BusBlock_balance(electricityBus_1_2)_: ++1 flow(powerplant_gas_coal_electricityBus_1_2) = 0 -c_e_BusBlock_balance(coalBus_1_3)_: -+1 flow(coalBus_powerplant_gas_coal_1_3) +c_e_BusBlock_balance(electricityBus_1_3)_: ++1 flow(powerplant_gas_coal_electricityBus_1_3) = 0 -c_e_BusBlock_balance(coalBus_2_4)_: -+1 flow(coalBus_powerplant_gas_coal_2_4) +c_e_BusBlock_balance(electricityBus_2_4)_: ++1 flow(powerplant_gas_coal_electricityBus_2_4) = 0 -c_e_BusBlock_balance(coalBus_2_5)_: -+1 flow(coalBus_powerplant_gas_coal_2_5) +c_e_BusBlock_balance(electricityBus_2_5)_: ++1 flow(powerplant_gas_coal_electricityBus_2_5) = 0 c_e_BusBlock_balance(gasBus_0_0)_: @@ -68,30 +68,6 @@ c_e_BusBlock_balance(gasBus_2_5)_: +1 flow(gasBus_powerplant_gas_coal_2_5) = 0 -c_e_BusBlock_balance(electricityBus_0_0)_: -+1 flow(powerplant_gas_coal_electricityBus_0_0) -= 0 - -c_e_BusBlock_balance(electricityBus_0_1)_: -+1 flow(powerplant_gas_coal_electricityBus_0_1) -= 0 - -c_e_BusBlock_balance(electricityBus_1_2)_: -+1 flow(powerplant_gas_coal_electricityBus_1_2) -= 0 - -c_e_BusBlock_balance(electricityBus_1_3)_: -+1 flow(powerplant_gas_coal_electricityBus_1_3) -= 0 - -c_e_BusBlock_balance(electricityBus_2_4)_: -+1 flow(powerplant_gas_coal_electricityBus_2_4) -= 0 - -c_e_BusBlock_balance(electricityBus_2_5)_: -+1 flow(powerplant_gas_coal_electricityBus_2_5) -= 0 - c_e_BusBlock_balance(thermalBus_0_0)_: +1 flow(powerplant_gas_coal_thermalBus_0_0) = 0 @@ -116,9 +92,28 @@ c_e_BusBlock_balance(thermalBus_2_5)_: +1 flow(powerplant_gas_coal_thermalBus_2_5) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_0)_: --0.2 flow(powerplant_gas_coal_electricityBus_0_0) -+0.3 flow(coalBus_powerplant_gas_coal_0_0) +c_e_BusBlock_balance(coalBus_0_0)_: ++1 flow(coalBus_powerplant_gas_coal_0_0) += 0 + +c_e_BusBlock_balance(coalBus_0_1)_: ++1 flow(coalBus_powerplant_gas_coal_0_1) += 0 + +c_e_BusBlock_balance(coalBus_1_2)_: ++1 flow(coalBus_powerplant_gas_coal_1_2) += 0 + +c_e_BusBlock_balance(coalBus_1_3)_: ++1 flow(coalBus_powerplant_gas_coal_1_3) += 0 + +c_e_BusBlock_balance(coalBus_2_4)_: ++1 flow(coalBus_powerplant_gas_coal_2_4) += 0 + +c_e_BusBlock_balance(coalBus_2_5)_: ++1 flow(coalBus_powerplant_gas_coal_2_5) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_0)_: @@ -126,9 +121,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_0)_: +0.3 flow(gasBus_powerplant_gas_coal_0_0) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_0)_: --0.2 flow(powerplant_gas_coal_thermalBus_0_0) -+0.5 flow(coalBus_powerplant_gas_coal_0_0) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_0)_: +-0.2 flow(powerplant_gas_coal_electricityBus_0_0) ++0.3 flow(coalBus_powerplant_gas_coal_0_0) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_0)_: @@ -136,9 +131,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_0)_: +0.5 flow(gasBus_powerplant_gas_coal_0_0) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_1)_: --0.2 flow(powerplant_gas_coal_electricityBus_0_1) -+0.3 flow(coalBus_powerplant_gas_coal_0_1) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_0)_: +-0.2 flow(powerplant_gas_coal_thermalBus_0_0) ++0.5 flow(coalBus_powerplant_gas_coal_0_0) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_1)_: @@ -146,9 +141,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_1)_: +0.3 flow(gasBus_powerplant_gas_coal_0_1) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_1)_: --0.2 flow(powerplant_gas_coal_thermalBus_0_1) -+0.5 flow(coalBus_powerplant_gas_coal_0_1) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_1)_: +-0.2 flow(powerplant_gas_coal_electricityBus_0_1) ++0.3 flow(coalBus_powerplant_gas_coal_0_1) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_1)_: @@ -156,9 +151,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_1)_: +0.5 flow(gasBus_powerplant_gas_coal_0_1) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_2)_: --0.2 flow(powerplant_gas_coal_electricityBus_1_2) -+0.3 flow(coalBus_powerplant_gas_coal_1_2) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_1)_: +-0.2 flow(powerplant_gas_coal_thermalBus_0_1) ++0.5 flow(coalBus_powerplant_gas_coal_0_1) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_2)_: @@ -166,9 +161,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_2)_: +0.3 flow(gasBus_powerplant_gas_coal_1_2) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_2)_: --0.2 flow(powerplant_gas_coal_thermalBus_1_2) -+0.5 flow(coalBus_powerplant_gas_coal_1_2) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_2)_: +-0.2 flow(powerplant_gas_coal_electricityBus_1_2) ++0.3 flow(coalBus_powerplant_gas_coal_1_2) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_2)_: @@ -176,9 +171,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_2)_: +0.5 flow(gasBus_powerplant_gas_coal_1_2) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_3)_: --0.2 flow(powerplant_gas_coal_electricityBus_1_3) -+0.3 flow(coalBus_powerplant_gas_coal_1_3) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_2)_: +-0.2 flow(powerplant_gas_coal_thermalBus_1_2) ++0.5 flow(coalBus_powerplant_gas_coal_1_2) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_3)_: @@ -186,9 +181,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_3)_: +0.3 flow(gasBus_powerplant_gas_coal_1_3) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_3)_: --0.2 flow(powerplant_gas_coal_thermalBus_1_3) -+0.5 flow(coalBus_powerplant_gas_coal_1_3) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_3)_: +-0.2 flow(powerplant_gas_coal_electricityBus_1_3) ++0.3 flow(coalBus_powerplant_gas_coal_1_3) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_3)_: @@ -196,9 +191,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_3)_: +0.5 flow(gasBus_powerplant_gas_coal_1_3) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_4)_: --0.2 flow(powerplant_gas_coal_electricityBus_2_4) -+0.3 flow(coalBus_powerplant_gas_coal_2_4) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_3)_: +-0.2 flow(powerplant_gas_coal_thermalBus_1_3) ++0.5 flow(coalBus_powerplant_gas_coal_1_3) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_4)_: @@ -206,9 +201,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_4)_: +0.3 flow(gasBus_powerplant_gas_coal_2_4) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_4)_: --0.2 flow(powerplant_gas_coal_thermalBus_2_4) -+0.5 flow(coalBus_powerplant_gas_coal_2_4) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_4)_: +-0.2 flow(powerplant_gas_coal_electricityBus_2_4) ++0.3 flow(coalBus_powerplant_gas_coal_2_4) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_4)_: @@ -216,9 +211,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_4)_: +0.5 flow(gasBus_powerplant_gas_coal_2_4) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_5)_: --0.2 flow(powerplant_gas_coal_electricityBus_2_5) -+0.3 flow(coalBus_powerplant_gas_coal_2_5) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_4)_: +-0.2 flow(powerplant_gas_coal_thermalBus_2_4) ++0.5 flow(coalBus_powerplant_gas_coal_2_4) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_5)_: @@ -226,9 +221,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_5)_: +0.3 flow(gasBus_powerplant_gas_coal_2_5) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_5)_: --0.2 flow(powerplant_gas_coal_thermalBus_2_5) -+0.5 flow(coalBus_powerplant_gas_coal_2_5) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_5)_: +-0.2 flow(powerplant_gas_coal_electricityBus_2_5) ++0.3 flow(coalBus_powerplant_gas_coal_2_5) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_5)_: @@ -236,6 +231,11 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_5)_: +0.5 flow(gasBus_powerplant_gas_coal_2_5) = 0 +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_5)_: +-0.2 flow(powerplant_gas_coal_thermalBus_2_5) ++0.5 flow(coalBus_powerplant_gas_coal_2_5) += 0 + c_e_InvestmentFlowBlock_total_rule(powerplant_gas_coal_electricityBus_0)_: -1 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) +1 InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_0) @@ -343,18 +343,18 @@ bounds 0 <= flow(powerplant_gas_coal_thermalBus_1_3) <= +inf 0 <= flow(powerplant_gas_coal_thermalBus_2_4) <= +inf 0 <= flow(powerplant_gas_coal_thermalBus_2_5) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_0_0) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_0_1) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_1_2) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_1_3) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_2_4) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_2_5) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_0_0) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_0_1) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_1_2) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_1_3) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_2_4) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_2_5) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_0_0) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_0_1) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_1_2) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_1_3) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_2_4) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_2_5) <= +inf 0 <= InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old(powerplant_gas_coal_electricityBus_1) <= +inf diff --git a/tests/lp_files/converter_invest_with_existing_multi_period.lp b/tests/lp_files/converter_invest_with_existing_multi_period.lp index 1ef5b303f..e18a16e66 100644 --- a/tests/lp_files/converter_invest_with_existing_multi_period.lp +++ b/tests/lp_files/converter_invest_with_existing_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+20.601980198019806 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) -+20.1980198019802 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_1) -+19.801980198019805 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_2) ++20.0 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) ++19.6078431372549 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_1) ++9.706853038245011 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_2) +50 flow(powerplant_gas_coal_electricityBus_0_0) +50 flow(powerplant_gas_coal_electricityBus_0_1) +49.01960784313725 flow(powerplant_gas_coal_electricityBus_1_2) @@ -20,28 +20,28 @@ objective: s.t. -c_e_BusBlock_balance(coalBus_0_0)_: -+1 flow(coalBus_powerplant_gas_coal_0_0) +c_e_BusBlock_balance(electricityBus_0_0)_: ++1 flow(powerplant_gas_coal_electricityBus_0_0) = 0 -c_e_BusBlock_balance(coalBus_0_1)_: -+1 flow(coalBus_powerplant_gas_coal_0_1) +c_e_BusBlock_balance(electricityBus_0_1)_: ++1 flow(powerplant_gas_coal_electricityBus_0_1) = 0 -c_e_BusBlock_balance(coalBus_1_2)_: -+1 flow(coalBus_powerplant_gas_coal_1_2) +c_e_BusBlock_balance(electricityBus_1_2)_: ++1 flow(powerplant_gas_coal_electricityBus_1_2) = 0 -c_e_BusBlock_balance(coalBus_1_3)_: -+1 flow(coalBus_powerplant_gas_coal_1_3) +c_e_BusBlock_balance(electricityBus_1_3)_: ++1 flow(powerplant_gas_coal_electricityBus_1_3) = 0 -c_e_BusBlock_balance(coalBus_2_4)_: -+1 flow(coalBus_powerplant_gas_coal_2_4) +c_e_BusBlock_balance(electricityBus_2_4)_: ++1 flow(powerplant_gas_coal_electricityBus_2_4) = 0 -c_e_BusBlock_balance(coalBus_2_5)_: -+1 flow(coalBus_powerplant_gas_coal_2_5) +c_e_BusBlock_balance(electricityBus_2_5)_: ++1 flow(powerplant_gas_coal_electricityBus_2_5) = 0 c_e_BusBlock_balance(gasBus_0_0)_: @@ -68,30 +68,6 @@ c_e_BusBlock_balance(gasBus_2_5)_: +1 flow(gasBus_powerplant_gas_coal_2_5) = 0 -c_e_BusBlock_balance(electricityBus_0_0)_: -+1 flow(powerplant_gas_coal_electricityBus_0_0) -= 0 - -c_e_BusBlock_balance(electricityBus_0_1)_: -+1 flow(powerplant_gas_coal_electricityBus_0_1) -= 0 - -c_e_BusBlock_balance(electricityBus_1_2)_: -+1 flow(powerplant_gas_coal_electricityBus_1_2) -= 0 - -c_e_BusBlock_balance(electricityBus_1_3)_: -+1 flow(powerplant_gas_coal_electricityBus_1_3) -= 0 - -c_e_BusBlock_balance(electricityBus_2_4)_: -+1 flow(powerplant_gas_coal_electricityBus_2_4) -= 0 - -c_e_BusBlock_balance(electricityBus_2_5)_: -+1 flow(powerplant_gas_coal_electricityBus_2_5) -= 0 - c_e_BusBlock_balance(thermalBus_0_0)_: +1 flow(powerplant_gas_coal_thermalBus_0_0) = 0 @@ -116,9 +92,28 @@ c_e_BusBlock_balance(thermalBus_2_5)_: +1 flow(powerplant_gas_coal_thermalBus_2_5) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_0)_: --0.2 flow(powerplant_gas_coal_electricityBus_0_0) -+0.3 flow(coalBus_powerplant_gas_coal_0_0) +c_e_BusBlock_balance(coalBus_0_0)_: ++1 flow(coalBus_powerplant_gas_coal_0_0) += 0 + +c_e_BusBlock_balance(coalBus_0_1)_: ++1 flow(coalBus_powerplant_gas_coal_0_1) += 0 + +c_e_BusBlock_balance(coalBus_1_2)_: ++1 flow(coalBus_powerplant_gas_coal_1_2) += 0 + +c_e_BusBlock_balance(coalBus_1_3)_: ++1 flow(coalBus_powerplant_gas_coal_1_3) += 0 + +c_e_BusBlock_balance(coalBus_2_4)_: ++1 flow(coalBus_powerplant_gas_coal_2_4) += 0 + +c_e_BusBlock_balance(coalBus_2_5)_: ++1 flow(coalBus_powerplant_gas_coal_2_5) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_0)_: @@ -126,9 +121,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_0)_: +0.3 flow(gasBus_powerplant_gas_coal_0_0) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_0)_: --0.2 flow(powerplant_gas_coal_thermalBus_0_0) -+0.5 flow(coalBus_powerplant_gas_coal_0_0) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_0)_: +-0.2 flow(powerplant_gas_coal_electricityBus_0_0) ++0.3 flow(coalBus_powerplant_gas_coal_0_0) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_0)_: @@ -136,9 +131,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_0)_: +0.5 flow(gasBus_powerplant_gas_coal_0_0) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_1)_: --0.2 flow(powerplant_gas_coal_electricityBus_0_1) -+0.3 flow(coalBus_powerplant_gas_coal_0_1) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_0)_: +-0.2 flow(powerplant_gas_coal_thermalBus_0_0) ++0.5 flow(coalBus_powerplant_gas_coal_0_0) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_1)_: @@ -146,9 +141,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_1)_: +0.3 flow(gasBus_powerplant_gas_coal_0_1) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_1)_: --0.2 flow(powerplant_gas_coal_thermalBus_0_1) -+0.5 flow(coalBus_powerplant_gas_coal_0_1) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_1)_: +-0.2 flow(powerplant_gas_coal_electricityBus_0_1) ++0.3 flow(coalBus_powerplant_gas_coal_0_1) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_1)_: @@ -156,9 +151,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_1)_: +0.5 flow(gasBus_powerplant_gas_coal_0_1) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_2)_: --0.2 flow(powerplant_gas_coal_electricityBus_1_2) -+0.3 flow(coalBus_powerplant_gas_coal_1_2) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_1)_: +-0.2 flow(powerplant_gas_coal_thermalBus_0_1) ++0.5 flow(coalBus_powerplant_gas_coal_0_1) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_2)_: @@ -166,9 +161,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_2)_: +0.3 flow(gasBus_powerplant_gas_coal_1_2) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_2)_: --0.2 flow(powerplant_gas_coal_thermalBus_1_2) -+0.5 flow(coalBus_powerplant_gas_coal_1_2) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_2)_: +-0.2 flow(powerplant_gas_coal_electricityBus_1_2) ++0.3 flow(coalBus_powerplant_gas_coal_1_2) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_2)_: @@ -176,9 +171,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_2)_: +0.5 flow(gasBus_powerplant_gas_coal_1_2) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_3)_: --0.2 flow(powerplant_gas_coal_electricityBus_1_3) -+0.3 flow(coalBus_powerplant_gas_coal_1_3) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_2)_: +-0.2 flow(powerplant_gas_coal_thermalBus_1_2) ++0.5 flow(coalBus_powerplant_gas_coal_1_2) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_3)_: @@ -186,9 +181,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_3)_: +0.3 flow(gasBus_powerplant_gas_coal_1_3) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_3)_: --0.2 flow(powerplant_gas_coal_thermalBus_1_3) -+0.5 flow(coalBus_powerplant_gas_coal_1_3) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_3)_: +-0.2 flow(powerplant_gas_coal_electricityBus_1_3) ++0.3 flow(coalBus_powerplant_gas_coal_1_3) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_3)_: @@ -196,9 +191,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_3)_: +0.5 flow(gasBus_powerplant_gas_coal_1_3) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_4)_: --0.2 flow(powerplant_gas_coal_electricityBus_2_4) -+0.3 flow(coalBus_powerplant_gas_coal_2_4) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_3)_: +-0.2 flow(powerplant_gas_coal_thermalBus_1_3) ++0.5 flow(coalBus_powerplant_gas_coal_1_3) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_4)_: @@ -206,9 +201,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_4)_: +0.3 flow(gasBus_powerplant_gas_coal_2_4) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_4)_: --0.2 flow(powerplant_gas_coal_thermalBus_2_4) -+0.5 flow(coalBus_powerplant_gas_coal_2_4) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_4)_: +-0.2 flow(powerplant_gas_coal_electricityBus_2_4) ++0.3 flow(coalBus_powerplant_gas_coal_2_4) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_4)_: @@ -216,9 +211,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_4)_: +0.5 flow(gasBus_powerplant_gas_coal_2_4) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_5)_: --0.2 flow(powerplant_gas_coal_electricityBus_2_5) -+0.3 flow(coalBus_powerplant_gas_coal_2_5) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_4)_: +-0.2 flow(powerplant_gas_coal_thermalBus_2_4) ++0.5 flow(coalBus_powerplant_gas_coal_2_4) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_5)_: @@ -226,9 +221,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_5)_: +0.3 flow(gasBus_powerplant_gas_coal_2_5) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_5)_: --0.2 flow(powerplant_gas_coal_thermalBus_2_5) -+0.5 flow(coalBus_powerplant_gas_coal_2_5) +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_5)_: +-0.2 flow(powerplant_gas_coal_electricityBus_2_5) ++0.3 flow(coalBus_powerplant_gas_coal_2_5) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_5)_: @@ -236,6 +231,11 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_5)_: +0.5 flow(gasBus_powerplant_gas_coal_2_5) = 0 +c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_5)_: +-0.2 flow(powerplant_gas_coal_thermalBus_2_5) ++0.5 flow(coalBus_powerplant_gas_coal_2_5) += 0 + c_e_InvestmentFlowBlock_total_rule(powerplant_gas_coal_electricityBus_0)_: -1 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) +1 InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_0) @@ -344,18 +344,18 @@ bounds 0 <= flow(powerplant_gas_coal_thermalBus_1_3) <= +inf 0 <= flow(powerplant_gas_coal_thermalBus_2_4) <= +inf 0 <= flow(powerplant_gas_coal_thermalBus_2_5) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_0_0) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_0_1) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_1_2) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_1_3) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_2_4) <= +inf - 0 <= flow(coalBus_powerplant_gas_coal_2_5) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_0_0) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_0_1) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_1_2) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_1_3) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_2_4) <= +inf 0 <= flow(gasBus_powerplant_gas_coal_2_5) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_0_0) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_0_1) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_1_2) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_1_3) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_2_4) <= +inf + 0 <= flow(coalBus_powerplant_gas_coal_2_5) <= +inf 0 <= InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old(powerplant_gas_coal_electricityBus_1) <= +inf diff --git a/tests/lp_files/dsm_module_DIW_invest_multi_period.lp b/tests/lp_files/dsm_module_DIW_invest_multi_period.lp index a03022363..68ad9b43c 100644 --- a/tests/lp_files/dsm_module_DIW_invest_multi_period.lp +++ b/tests/lp_files/dsm_module_DIW_invest_multi_period.lp @@ -2,7 +2,7 @@ min objective: -+15992.031251718836 ONE_VAR_CONSTANT ++2941.5609381007307 ONE_VAR_CONSTANT +1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_0) +1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_0) +1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_0) @@ -51,9 +51,9 @@ objective: +0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_5) +0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) +96.11687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) -+455.88267648036174 SinkDSMDIWInvestmentBlock_invest(demand_dsm_0) -+440.53147366914004 SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) -+425.7302732994234 SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) ++76.46810240317063 SinkDSMDIWInvestmentBlock_invest(demand_dsm_0) ++49.710949277906536 SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) ++24.239842660236203 SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) s.t. diff --git a/tests/lp_files/dsm_module_DLR_invest_multi_period.lp b/tests/lp_files/dsm_module_DLR_invest_multi_period.lp index ff00f7ab2..3fb7aa6fd 100644 --- a/tests/lp_files/dsm_module_DLR_invest_multi_period.lp +++ b/tests/lp_files/dsm_module_DLR_invest_multi_period.lp @@ -2,7 +2,7 @@ min objective: -+15992.031251718836 ONE_VAR_CONSTANT ++2941.5609381007307 ONE_VAR_CONSTANT +1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_0) +1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_0) +1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_0) @@ -57,9 +57,9 @@ objective: +0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_5) +0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) +96.11687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) -+455.88267648036174 SinkDSMDLRInvestmentBlock_invest(demand_dsm_0) -+440.53147366914004 SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) -+425.7302732994234 SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) ++76.46810240317063 SinkDSMDLRInvestmentBlock_invest(demand_dsm_0) ++49.710949277906536 SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) ++24.239842660236203 SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) s.t. @@ -623,13 +623,13 @@ c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_inc(demand_dsm_2_5)_: c_u_SinkDSMDLRInvestmentBlock_dr_yearly_limit_shed(demand_dsm_0)_: +1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_0) +1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_1) --50 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +-50.0 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) <= 0 c_u_SinkDSMDLRInvestmentBlock_dr_yearly_limit_shed(demand_dsm_1)_: +1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_2) +1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_3) --50 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +-50.0 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) <= 0 c_u_SinkDSMDLRInvestmentBlock_dr_yearly_limit_shed(demand_dsm_2)_: diff --git a/tests/lp_files/dsm_module_oemof_invest_multi_period.lp b/tests/lp_files/dsm_module_oemof_invest_multi_period.lp index 016b262d0..b92f80115 100644 --- a/tests/lp_files/dsm_module_oemof_invest_multi_period.lp +++ b/tests/lp_files/dsm_module_oemof_invest_multi_period.lp @@ -2,7 +2,7 @@ min objective: -+15992.031251718836 ONE_VAR_CONSTANT ++2941.5609381007307 ONE_VAR_CONSTANT +1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_0) +100 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_0) +1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_0) @@ -21,9 +21,9 @@ objective: +0.9611687812379853 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_5) +0.9611687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_5) +96.11687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_5) -+455.88267648036174 SinkDSMOemofInvestmentBlock_invest(demand_dsm_0) -+440.53147366914004 SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) -+425.7302732994234 SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) ++76.46810240317063 SinkDSMOemofInvestmentBlock_invest(demand_dsm_0) ++49.710949277906536 SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) ++24.239842660236203 SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) s.t. diff --git a/tests/lp_files/fixed_source_invest_sink_multi_period.lp b/tests/lp_files/fixed_source_invest_sink_multi_period.lp index bbfaa46fb..af511ec32 100644 --- a/tests/lp_files/fixed_source_invest_sink_multi_period.lp +++ b/tests/lp_files/fixed_source_invest_sink_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+611.5671812529034 InvestmentFlowBlock_invest(electricityBus_excess_0) -+599.5756678950033 InvestmentFlowBlock_invest(electricityBus_excess_1) -+587.8192822500032 InvestmentFlowBlock_invest(electricityBus_excess_2) ++88.1844182057801 InvestmentFlowBlock_invest(electricityBus_excess_0) ++58.20563481102971 InvestmentFlowBlock_invest(electricityBus_excess_1) ++28.814670698529593 InvestmentFlowBlock_invest(electricityBus_excess_2) +25 flow(electricityBus_excess_0_0) +25 flow(electricityBus_excess_0_1) +24.509803921568626 flow(electricityBus_excess_1_2) diff --git a/tests/lp_files/flow_invest_with_offset_multi_period.lp b/tests/lp_files/flow_invest_with_offset_multi_period.lp index 1954c450c..5e4510206 100644 --- a/tests/lp_files/flow_invest_with_offset_multi_period.lp +++ b/tests/lp_files/flow_invest_with_offset_multi_period.lp @@ -2,11 +2,11 @@ min objective: -+611.5671812529034 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) ++88.1844182057801 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) +34 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_0) -+599.5756678950033 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) ++58.20563481102971 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) +33.33333333333333 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_1) -+587.8192822500032 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) ++28.814670698529593 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) +32.6797385620915 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_2) +25 flow(source_nonconvex_invest_electricityBus_0_0) +25 flow(source_nonconvex_invest_electricityBus_0_1) diff --git a/tests/lp_files/flow_invest_with_offset_no_minimum_multi_period.lp b/tests/lp_files/flow_invest_with_offset_no_minimum_multi_period.lp index 462f594da..6ff9b91de 100644 --- a/tests/lp_files/flow_invest_with_offset_no_minimum_multi_period.lp +++ b/tests/lp_files/flow_invest_with_offset_no_minimum_multi_period.lp @@ -2,11 +2,11 @@ min objective: -+611.5671812529034 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) ++88.1844182057801 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) +34 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_0) -+599.5756678950033 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) ++58.20563481102971 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) +33.33333333333333 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_1) -+587.8192822500032 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) ++28.814670698529593 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) +32.6797385620915 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_2) +25 flow(source_nonconvex_invest_electricityBus_0_0) +25 flow(source_nonconvex_invest_electricityBus_0_1) diff --git a/tests/lp_files/flow_invest_without_offset_multi_period.lp b/tests/lp_files/flow_invest_without_offset_multi_period.lp index 4ce5cd340..40b7e34a1 100644 --- a/tests/lp_files/flow_invest_without_offset_multi_period.lp +++ b/tests/lp_files/flow_invest_without_offset_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+611.5671812529034 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_0) -+599.5756678950033 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_1) -+587.8192822500032 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_2) ++88.1844182057801 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_0) ++58.20563481102971 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_1) ++28.814670698529593 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_2) +25 flow(electricityBus_sink_nonconvex_invest_0_0) +25 flow(electricityBus_sink_nonconvex_invest_0_1) +24.509803921568626 flow(electricityBus_sink_nonconvex_invest_1_2) diff --git a/tests/lp_files/invest_source_fixed_sink_multi_period.lp b/tests/lp_files/invest_source_fixed_sink_multi_period.lp index b0f28add1..b549928ee 100644 --- a/tests/lp_files/invest_source_fixed_sink_multi_period.lp +++ b/tests/lp_files/invest_source_fixed_sink_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+157.5028481334886 InvestmentFlowBlock_invest(pv_electricityBus_0) -+154.4145569936163 InvestmentFlowBlock_invest(pv_electricityBus_1) -+151.38682058197674 InvestmentFlowBlock_invest(pv_electricityBus_2) ++18.16879316506207 InvestmentFlowBlock_invest(pv_electricityBus_0) ++11.99221088531737 InvestmentFlowBlock_invest(pv_electricityBus_1) ++5.93673806203831 InvestmentFlowBlock_invest(pv_electricityBus_2) +13 flow(pv_electricityBus_0_0) +13 flow(pv_electricityBus_0_1) +12.745098039215685 flow(pv_electricityBus_1_2) diff --git a/tests/lp_files/linear_converter_chp_invest_multi_period.lp b/tests/lp_files/linear_converter_chp_invest_multi_period.lp index 5b4da4858..9a52152a5 100644 --- a/tests/lp_files/linear_converter_chp_invest_multi_period.lp +++ b/tests/lp_files/linear_converter_chp_invest_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+31.82320970369655 InvestmentFlowBlock_invest(gasBus_chp_powerplant_gas_0) -+31.199225199702497 InvestmentFlowBlock_invest(gasBus_chp_powerplant_gas_1) -+30.587475685982838 InvestmentFlowBlock_invest(gasBus_chp_powerplant_gas_2) ++1.8354884429290608 InvestmentFlowBlock_invest(gasBus_chp_powerplant_gas_0) ++1.2115039389350062 InvestmentFlowBlock_invest(gasBus_chp_powerplant_gas_1) ++0.5997544252153503 InvestmentFlowBlock_invest(gasBus_chp_powerplant_gas_2) +50 flow(gasBus_chp_powerplant_gas_0_0) +50 flow(gasBus_chp_powerplant_gas_0_1) +49.01960784313725 flow(gasBus_chp_powerplant_gas_1_2) @@ -14,6 +14,30 @@ objective: s.t. +c_e_BusBlock_balance(heatBus_0_0)_: ++1 flow(chp_powerplant_gas_heatBus_0_0) += 0 + +c_e_BusBlock_balance(heatBus_0_1)_: ++1 flow(chp_powerplant_gas_heatBus_0_1) += 0 + +c_e_BusBlock_balance(heatBus_1_2)_: ++1 flow(chp_powerplant_gas_heatBus_1_2) += 0 + +c_e_BusBlock_balance(heatBus_1_3)_: ++1 flow(chp_powerplant_gas_heatBus_1_3) += 0 + +c_e_BusBlock_balance(heatBus_2_4)_: ++1 flow(chp_powerplant_gas_heatBus_2_4) += 0 + +c_e_BusBlock_balance(heatBus_2_5)_: ++1 flow(chp_powerplant_gas_heatBus_2_5) += 0 + c_e_BusBlock_balance(gasBus_0_0)_: +1 flow(gasBus_chp_powerplant_gas_0_0) = 0 @@ -62,30 +86,6 @@ c_e_BusBlock_balance(electricityBus_2_5)_: +1 flow(chp_powerplant_gas_electricityBus_2_5) = 0 -c_e_BusBlock_balance(heatBus_0_0)_: -+1 flow(chp_powerplant_gas_heatBus_0_0) -= 0 - -c_e_BusBlock_balance(heatBus_0_1)_: -+1 flow(chp_powerplant_gas_heatBus_0_1) -= 0 - -c_e_BusBlock_balance(heatBus_1_2)_: -+1 flow(chp_powerplant_gas_heatBus_1_2) -= 0 - -c_e_BusBlock_balance(heatBus_1_3)_: -+1 flow(chp_powerplant_gas_heatBus_1_3) -= 0 - -c_e_BusBlock_balance(heatBus_2_4)_: -+1 flow(chp_powerplant_gas_heatBus_2_4) -= 0 - -c_e_BusBlock_balance(heatBus_2_5)_: -+1 flow(chp_powerplant_gas_heatBus_2_5) -= 0 - c_e_ConverterBlock_relation(chp_powerplant_gas_gasBus_electricityBus_0_0)_: +0.4 flow(gasBus_chp_powerplant_gas_0_0) -1 flow(chp_powerplant_gas_electricityBus_0_0) @@ -247,18 +247,18 @@ bounds 0 <= flow(gasBus_chp_powerplant_gas_1_3) <= +inf 0 <= flow(gasBus_chp_powerplant_gas_2_4) <= +inf 0 <= flow(gasBus_chp_powerplant_gas_2_5) <= +inf - 0 <= flow(chp_powerplant_gas_electricityBus_0_0) <= +inf - 0 <= flow(chp_powerplant_gas_electricityBus_0_1) <= +inf - 0 <= flow(chp_powerplant_gas_electricityBus_1_2) <= +inf - 0 <= flow(chp_powerplant_gas_electricityBus_1_3) <= +inf - 0 <= flow(chp_powerplant_gas_electricityBus_2_4) <= +inf - 0 <= flow(chp_powerplant_gas_electricityBus_2_5) <= +inf 0 <= flow(chp_powerplant_gas_heatBus_0_0) <= +inf 0 <= flow(chp_powerplant_gas_heatBus_0_1) <= +inf 0 <= flow(chp_powerplant_gas_heatBus_1_2) <= +inf 0 <= flow(chp_powerplant_gas_heatBus_1_3) <= +inf 0 <= flow(chp_powerplant_gas_heatBus_2_4) <= +inf 0 <= flow(chp_powerplant_gas_heatBus_2_5) <= +inf + 0 <= flow(chp_powerplant_gas_electricityBus_0_0) <= +inf + 0 <= flow(chp_powerplant_gas_electricityBus_0_1) <= +inf + 0 <= flow(chp_powerplant_gas_electricityBus_1_2) <= +inf + 0 <= flow(chp_powerplant_gas_electricityBus_1_3) <= +inf + 0 <= flow(chp_powerplant_gas_electricityBus_2_4) <= +inf + 0 <= flow(chp_powerplant_gas_electricityBus_2_5) <= +inf 0 <= InvestmentFlowBlock_total(gasBus_chp_powerplant_gas_0) <= +inf 0 <= InvestmentFlowBlock_total(gasBus_chp_powerplant_gas_1) <= +inf 0 <= InvestmentFlowBlock_old(gasBus_chp_powerplant_gas_1) <= +inf diff --git a/tests/lp_files/linear_converter_invest_multi_period.lp b/tests/lp_files/linear_converter_invest_multi_period.lp index 61139ae3d..325b7b0a1 100644 --- a/tests/lp_files/linear_converter_invest_multi_period.lp +++ b/tests/lp_files/linear_converter_invest_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+29.24459823787798 InvestmentFlowBlock_invest(powerplant_gas_electricity_0) -+28.671174743017627 InvestmentFlowBlock_invest(powerplant_gas_electricity_1) -+28.10899484609571 InvestmentFlowBlock_invest(powerplant_gas_electricity_2) ++2.1084501918380276 InvestmentFlowBlock_invest(powerplant_gas_electricity_0) ++1.3916708232625816 InvestmentFlowBlock_invest(powerplant_gas_electricity_1) ++0.6889459521101896 InvestmentFlowBlock_invest(powerplant_gas_electricity_2) +50 flow(powerplant_gas_electricity_0_0) +50 flow(powerplant_gas_electricity_0_1) +49.01960784313725 flow(powerplant_gas_electricity_1_2) @@ -14,30 +14,6 @@ objective: s.t. -c_e_BusBlock_balance(gas_0_0)_: -+1 flow(gas_powerplant_gas_0_0) -= 0 - -c_e_BusBlock_balance(gas_0_1)_: -+1 flow(gas_powerplant_gas_0_1) -= 0 - -c_e_BusBlock_balance(gas_1_2)_: -+1 flow(gas_powerplant_gas_1_2) -= 0 - -c_e_BusBlock_balance(gas_1_3)_: -+1 flow(gas_powerplant_gas_1_3) -= 0 - -c_e_BusBlock_balance(gas_2_4)_: -+1 flow(gas_powerplant_gas_2_4) -= 0 - -c_e_BusBlock_balance(gas_2_5)_: -+1 flow(gas_powerplant_gas_2_5) -= 0 - c_e_BusBlock_balance(electricity_0_0)_: +1 flow(powerplant_gas_electricity_0_0) = 0 @@ -62,6 +38,30 @@ c_e_BusBlock_balance(electricity_2_5)_: +1 flow(powerplant_gas_electricity_2_5) = 0 +c_e_BusBlock_balance(gas_0_0)_: ++1 flow(gas_powerplant_gas_0_0) += 0 + +c_e_BusBlock_balance(gas_0_1)_: ++1 flow(gas_powerplant_gas_0_1) += 0 + +c_e_BusBlock_balance(gas_1_2)_: ++1 flow(gas_powerplant_gas_1_2) += 0 + +c_e_BusBlock_balance(gas_1_3)_: ++1 flow(gas_powerplant_gas_1_3) += 0 + +c_e_BusBlock_balance(gas_2_4)_: ++1 flow(gas_powerplant_gas_2_4) += 0 + +c_e_BusBlock_balance(gas_2_5)_: ++1 flow(gas_powerplant_gas_2_5) += 0 + c_e_ConverterBlock_relation(powerplant_gas_gas_electricity_0_0)_: -1 flow(powerplant_gas_electricity_0_0) +0.58 flow(gas_powerplant_gas_0_0) diff --git a/tests/lp_files/linear_converter_invest_multi_period_old.lp b/tests/lp_files/linear_converter_invest_multi_period_old.lp index dc0921e45..5ddc28a1f 100644 --- a/tests/lp_files/linear_converter_invest_multi_period_old.lp +++ b/tests/lp_files/linear_converter_invest_multi_period_old.lp @@ -2,9 +2,9 @@ min objective: -+20.601980198019806 InvestmentFlowBlock_invest(powerplant_gas_electricity_0) -+20.1980198019802 InvestmentFlowBlock_invest(powerplant_gas_electricity_1) -+19.801980198019805 InvestmentFlowBlock_invest(powerplant_gas_electricity_2) ++20.0 InvestmentFlowBlock_invest(powerplant_gas_electricity_0) ++19.6078431372549 InvestmentFlowBlock_invest(powerplant_gas_electricity_1) ++9.706853038245011 InvestmentFlowBlock_invest(powerplant_gas_electricity_2) +50 flow(powerplant_gas_electricity_0_0) +50 flow(powerplant_gas_electricity_0_1) +49.01960784313725 flow(powerplant_gas_electricity_1_2) @@ -14,30 +14,6 @@ objective: s.t. -c_e_BusBlock_balance(gas_0_0)_: -+1 flow(gas_powerplant_gas_0_0) -= 0 - -c_e_BusBlock_balance(gas_0_1)_: -+1 flow(gas_powerplant_gas_0_1) -= 0 - -c_e_BusBlock_balance(gas_1_2)_: -+1 flow(gas_powerplant_gas_1_2) -= 0 - -c_e_BusBlock_balance(gas_1_3)_: -+1 flow(gas_powerplant_gas_1_3) -= 0 - -c_e_BusBlock_balance(gas_2_4)_: -+1 flow(gas_powerplant_gas_2_4) -= 0 - -c_e_BusBlock_balance(gas_2_5)_: -+1 flow(gas_powerplant_gas_2_5) -= 0 - c_e_BusBlock_balance(electricity_0_0)_: +1 flow(powerplant_gas_electricity_0_0) = 0 @@ -62,6 +38,30 @@ c_e_BusBlock_balance(electricity_2_5)_: +1 flow(powerplant_gas_electricity_2_5) = 0 +c_e_BusBlock_balance(gas_0_0)_: ++1 flow(gas_powerplant_gas_0_0) += 0 + +c_e_BusBlock_balance(gas_0_1)_: ++1 flow(gas_powerplant_gas_0_1) += 0 + +c_e_BusBlock_balance(gas_1_2)_: ++1 flow(gas_powerplant_gas_1_2) += 0 + +c_e_BusBlock_balance(gas_1_3)_: ++1 flow(gas_powerplant_gas_1_3) += 0 + +c_e_BusBlock_balance(gas_2_4)_: ++1 flow(gas_powerplant_gas_2_4) += 0 + +c_e_BusBlock_balance(gas_2_5)_: ++1 flow(gas_powerplant_gas_2_5) += 0 + c_e_ConverterBlock_relation(powerplant_gas_gas_electricity_0_0)_: -1 flow(powerplant_gas_electricity_0_0) +0.58 flow(gas_powerplant_gas_0_0) diff --git a/tests/lp_files/multi_period_period_length.lp b/tests/lp_files/multi_period_period_length.lp index 66c20689e..8f7edb5d0 100644 --- a/tests/lp_files/multi_period_period_length.lp +++ b/tests/lp_files/multi_period_period_length.lp @@ -1,32 +1,32 @@ \* Source Pyomo model name=Model *\ -min +min objective: +15992.031251718836 ONE_VAR_CONSTANT -+12.231343625058066 InvestmentFlowBlock_invest(storage_electricity_0) -+8.231343625058066 InvestmentFlowBlock_invest(storage_electricity_1) -+6.116009561015236 InvestmentFlowBlock_invest(storage_electricity_2) -+5.017258045399043 InvestmentFlowBlock_invest(storage_electricity_3) -+4.544285192584936 InvestmentFlowBlock_invest(storage_electricity_4) -+3.7278966318848936 InvestmentFlowBlock_invest(storage_electricity_5) -+2.769882109365063 InvestmentFlowBlock_invest(storage_electricity_6) -+1.864051255691565 InvestmentFlowBlock_invest(storage_electricity_7) -+12.231343625058066 InvestmentFlowBlock_invest(electricity_storage_0) -+8.231343625058066 InvestmentFlowBlock_invest(electricity_storage_1) -+6.116009561015236 InvestmentFlowBlock_invest(electricity_storage_2) -+5.017258045399043 InvestmentFlowBlock_invest(electricity_storage_3) -+4.544285192584936 InvestmentFlowBlock_invest(electricity_storage_4) -+3.7278966318848936 InvestmentFlowBlock_invest(electricity_storage_5) -+2.769882109365063 InvestmentFlowBlock_invest(electricity_storage_6) -+1.864051255691565 InvestmentFlowBlock_invest(electricity_storage_7) -+12.231343625058066 GenericInvestmentStorageBlock_invest(storage_0) -+8.231343625058066 GenericInvestmentStorageBlock_invest(storage_1) -+6.116009561015236 GenericInvestmentStorageBlock_invest(storage_2) -+5.017258045399043 GenericInvestmentStorageBlock_invest(storage_3) -+4.544285192584936 GenericInvestmentStorageBlock_invest(storage_4) -+3.7278966318848936 GenericInvestmentStorageBlock_invest(storage_5) -+2.769882109365063 GenericInvestmentStorageBlock_invest(storage_6) -+1.864051255691565 GenericInvestmentStorageBlock_invest(storage_7) ++9.999999999999998 InvestmentFlowBlock_invest(storage_electricity_0) ++6.729713331080573 InvestmentFlowBlock_invest(storage_electricity_1) ++5.000276133592968 InvestmentFlowBlock_invest(storage_electricity_2) ++4.101968025099305 InvestmentFlowBlock_invest(storage_electricity_3) ++3.7152788212696146 InvestmentFlowBlock_invest(storage_electricity_4) ++3.0478226645906985 InvestmentFlowBlock_invest(storage_electricity_5) ++2.264577134183746 InvestmentFlowBlock_invest(storage_electricity_6) ++0.09137506155350818 InvestmentFlowBlock_invest(storage_electricity_7) ++9.999999999999998 InvestmentFlowBlock_invest(electricity_storage_0) ++6.729713331080573 InvestmentFlowBlock_invest(electricity_storage_1) ++5.000276133592968 InvestmentFlowBlock_invest(electricity_storage_2) ++4.101968025099305 InvestmentFlowBlock_invest(electricity_storage_3) ++3.7152788212696146 InvestmentFlowBlock_invest(electricity_storage_4) ++3.0478226645906985 InvestmentFlowBlock_invest(electricity_storage_5) ++2.264577134183746 InvestmentFlowBlock_invest(electricity_storage_6) ++0.09137506155350818 InvestmentFlowBlock_invest(electricity_storage_7) ++9.999999999999998 GenericInvestmentStorageBlock_invest(storage_0) ++6.729713331080573 GenericInvestmentStorageBlock_invest(storage_1) ++5.000276133592968 GenericInvestmentStorageBlock_invest(storage_2) ++4.101968025099305 GenericInvestmentStorageBlock_invest(storage_3) ++3.7152788212696146 GenericInvestmentStorageBlock_invest(storage_4) ++3.0478226645906985 GenericInvestmentStorageBlock_invest(storage_5) ++2.264577134183746 GenericInvestmentStorageBlock_invest(storage_6) ++0.09137506155350818 GenericInvestmentStorageBlock_invest(storage_7) +1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_diw_0_0) +1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_diw_1_0) +1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_diw_2_0) @@ -651,14 +651,14 @@ objective: +0.15239954929176602 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_diw_22_23) +0.15239954929176602 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_diw_23_23) +15.239954929176601 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_diw_23) -+455.88267648036174 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_0) -+233.38374795126995 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_1) -+144.56161688922427 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_2) -+106.29941341240747 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_3) -+91.48640392066359 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_4) -+68.26495688582924 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_5) -+44.80528445188661 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_6) -+26.387865849578166 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_7) ++433.5692402297811 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_0) ++218.36744501149502 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_1) ++133.4042826150016 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_2) ++97.1465132094101 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_3) ++83.19634020751037 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_4) ++61.46421721288727 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_5) ++39.75223470007343 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_6) ++1.3782630680217502 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_7) +1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_dlr_1_0) +1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_dlr_1_0) +1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_dlr_2_0) @@ -875,14 +875,14 @@ objective: +0.15239954929176602 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_dlr_2_23) +0.15239954929176602 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_dlr_2_23) +15.239954929176601 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_dlr_23) -+455.88267648036174 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_0) -+233.38374795126995 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_1) -+144.56161688922427 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_2) -+106.29941341240747 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_3) -+91.48640392066359 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_4) -+68.26495688582924 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_5) -+44.80528445188661 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_6) -+26.387865849578166 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_7) ++433.5692402297811 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_0) ++218.36744501149502 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_1) ++133.4042826150016 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_2) ++97.1465132094101 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_3) ++83.19634020751037 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_4) ++61.46421721288727 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_5) ++39.75223470007343 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_6) ++1.3782630680217502 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_7) +1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_oemof_0) +100 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_oemof_0) +1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_oemof_0) @@ -955,14 +955,14 @@ objective: +0.15239954929176602 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_oemof_23) +0.15239954929176602 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_oemof_23) +15.239954929176601 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_oemof_23) -+455.88267648036174 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_0) -+233.38374795126995 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_1) -+144.56161688922427 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_2) -+106.29941341240747 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_3) -+91.48640392066359 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_4) -+68.26495688582924 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_5) -+44.80528445188661 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_6) -+26.387865849578166 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_7) ++433.5692402297811 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_0) ++218.36744501149502 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_1) ++133.4042826150016 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_2) ++97.1465132094101 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_3) ++83.19634020751037 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_4) ++61.46421721288727 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_5) ++39.75223470007343 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_6) ++1.3782630680217502 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_7) s.t. @@ -1918,14 +1918,14 @@ c_e_GenericInvestmentStorageBlock_old_rule(storage_7)_: = 0 c_e_GenericInvestmentStorageBlock_initially_empty(storage_0)_: -1 GenericInvestmentStorageBlock_storage_content(storage_0) ++1 GenericInvestmentStorageBlock_storage_content(storage_0) = 0 c_e_GenericInvestmentStorageBlock_balance(storage_0_1)_: +1 flow(storage_electricity_0_1) -1 flow(electricity_storage_0_1) -+1 GenericInvestmentStorageBlock_storage_content(storage_1) -1 GenericInvestmentStorageBlock_storage_content(storage_0) ++1 GenericInvestmentStorageBlock_storage_content(storage_1) = 0 c_e_GenericInvestmentStorageBlock_balance(storage_0_2)_: @@ -7894,8 +7894,8 @@ bounds 0 <= GenericInvestmentStorageBlock_old_exo(storage_6) <= +inf 0 <= GenericInvestmentStorageBlock_old_exo(storage_7) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage_0) <= +inf - 0 <= GenericInvestmentStorageBlock_storage_content(storage_1) <= +inf 0 <= GenericInvestmentStorageBlock_storage_content(storage_0) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_1) <= +inf 0 <= GenericInvestmentStorageBlock_storage_content(storage_2) <= +inf 0 <= GenericInvestmentStorageBlock_storage_content(storage_3) <= +inf 0 <= GenericInvestmentStorageBlock_storage_content(storage_4) <= +inf diff --git a/tests/lp_files/periodical_investment_limit.lp b/tests/lp_files/periodical_investment_limit.lp index b6c76060f..1a01bf380 100644 --- a/tests/lp_files/periodical_investment_limit.lp +++ b/tests/lp_files/periodical_investment_limit.lp @@ -2,28 +2,28 @@ min objective: -+285.3937455128117 InvestmentFlowBlock_invest(Source_Bus1_0) -+279.7977897184428 InvestmentFlowBlock_invest(Source_Bus1_1) -+274.31155854749295 InvestmentFlowBlock_invest(Source_Bus1_2) -+194.22716197630274 GenericInvestmentStorageBlock_invest(storage_invest_limit_0) -+190.4187862512772 GenericInvestmentStorageBlock_invest(storage_invest_limit_1) -+186.68508456007567 GenericInvestmentStorageBlock_invest(storage_invest_limit_2) ++8.230422488026955 InvestmentFlowBlock_invest(Source_Bus1_0) ++5.432444590842506 InvestmentFlowBlock_invest(Source_Bus1_1) ++2.6893290053675805 InvestmentFlowBlock_invest(Source_Bus1_2) ++18.670948783910358 GenericInvestmentStorageBlock_invest(storage_invest_limit_0) ++12.323655908867737 GenericInvestmentStorageBlock_invest(storage_invest_limit_1) ++6.1008197568652225 GenericInvestmentStorageBlock_invest(storage_invest_limit_2) s.t. c_u_investment_limit_per_period(0)_: -+285.3937455128117 InvestmentFlowBlock_invest(Source_Bus1_0) -+194.22716197630274 GenericInvestmentStorageBlock_invest(storage_invest_limit_0) ++8.230422488026955 InvestmentFlowBlock_invest(Source_Bus1_0) ++18.670948783910358 GenericInvestmentStorageBlock_invest(storage_invest_limit_0) <= 500 c_u_investment_limit_per_period(1)_: -+279.7977897184428 InvestmentFlowBlock_invest(Source_Bus1_1) -+190.4187862512772 GenericInvestmentStorageBlock_invest(storage_invest_limit_1) ++5.432444590842506 InvestmentFlowBlock_invest(Source_Bus1_1) ++12.323655908867737 GenericInvestmentStorageBlock_invest(storage_invest_limit_1) <= 400 c_u_investment_limit_per_period(2)_: -+274.31155854749295 InvestmentFlowBlock_invest(Source_Bus1_2) -+186.68508456007567 GenericInvestmentStorageBlock_invest(storage_invest_limit_2) ++2.6893290053675805 InvestmentFlowBlock_invest(Source_Bus1_2) ++6.1008197568652225 GenericInvestmentStorageBlock_invest(storage_invest_limit_2) <= 300 c_e_BusBlock_balance(Bus1_0_0)_: @@ -81,25 +81,6 @@ c_e_InvestmentFlowBlock_total_rule(storage_invest_limit_Bus1_2)_: +1 InvestmentFlowBlock_old(storage_invest_limit_Bus1_2) = 0 -c_e_InvestmentFlowBlock_total_rule(Source_Bus1_0)_: --1 InvestmentFlowBlock_invest(Source_Bus1_0) -+1 InvestmentFlowBlock_total(Source_Bus1_0) -= 0 - -c_e_InvestmentFlowBlock_total_rule(Source_Bus1_1)_: --1 InvestmentFlowBlock_invest(Source_Bus1_1) --1 InvestmentFlowBlock_total(Source_Bus1_0) -+1 InvestmentFlowBlock_total(Source_Bus1_1) -+1 InvestmentFlowBlock_old(Source_Bus1_1) -= 0 - -c_e_InvestmentFlowBlock_total_rule(Source_Bus1_2)_: --1 InvestmentFlowBlock_invest(Source_Bus1_2) --1 InvestmentFlowBlock_total(Source_Bus1_1) -+1 InvestmentFlowBlock_total(Source_Bus1_2) -+1 InvestmentFlowBlock_old(Source_Bus1_2) -= 0 - c_e_InvestmentFlowBlock_total_rule(Bus1_storage_invest_limit_0)_: +1 InvestmentFlowBlock_total(Bus1_storage_invest_limit_0) -1 InvestmentFlowBlock_invest(Bus1_storage_invest_limit_0) @@ -119,28 +100,35 @@ c_e_InvestmentFlowBlock_total_rule(Bus1_storage_invest_limit_2)_: +1 InvestmentFlowBlock_old(Bus1_storage_invest_limit_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_invest_limit_Bus1_0)_: -+1 InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_0) +c_e_InvestmentFlowBlock_total_rule(Source_Bus1_0)_: +-1 InvestmentFlowBlock_invest(Source_Bus1_0) ++1 InvestmentFlowBlock_total(Source_Bus1_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_invest_limit_Bus1_1)_: -+1 InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_1) +c_e_InvestmentFlowBlock_total_rule(Source_Bus1_1)_: +-1 InvestmentFlowBlock_invest(Source_Bus1_1) +-1 InvestmentFlowBlock_total(Source_Bus1_0) ++1 InvestmentFlowBlock_total(Source_Bus1_1) ++1 InvestmentFlowBlock_old(Source_Bus1_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_invest_limit_Bus1_2)_: -+1 InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_2) +c_e_InvestmentFlowBlock_total_rule(Source_Bus1_2)_: +-1 InvestmentFlowBlock_invest(Source_Bus1_2) +-1 InvestmentFlowBlock_total(Source_Bus1_1) ++1 InvestmentFlowBlock_total(Source_Bus1_2) ++1 InvestmentFlowBlock_old(Source_Bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_0)_: -+1 InvestmentFlowBlock_old_end(Source_Bus1_0) +c_e_InvestmentFlowBlock_old_rule_end(storage_invest_limit_Bus1_0)_: ++1 InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_1)_: -+1 InvestmentFlowBlock_old_end(Source_Bus1_1) +c_e_InvestmentFlowBlock_old_rule_end(storage_invest_limit_Bus1_1)_: ++1 InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_2)_: -+1 InvestmentFlowBlock_old_end(Source_Bus1_2) +c_e_InvestmentFlowBlock_old_rule_end(storage_invest_limit_Bus1_2)_: ++1 InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(Bus1_storage_invest_limit_0)_: @@ -155,28 +143,28 @@ c_e_InvestmentFlowBlock_old_rule_end(Bus1_storage_invest_limit_2)_: +1 InvestmentFlowBlock_old_end(Bus1_storage_invest_limit_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_invest_limit_Bus1_0)_: -+1 InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_0) +c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_0)_: ++1 InvestmentFlowBlock_old_end(Source_Bus1_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_invest_limit_Bus1_1)_: -+1 InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_1) +c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_1)_: ++1 InvestmentFlowBlock_old_end(Source_Bus1_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_invest_limit_Bus1_2)_: -+1 InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_2) +c_e_InvestmentFlowBlock_old_rule_end(Source_Bus1_2)_: ++1 InvestmentFlowBlock_old_end(Source_Bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_0)_: -+1 InvestmentFlowBlock_old_exo(Source_Bus1_0) +c_e_InvestmentFlowBlock_old_rule_exo(storage_invest_limit_Bus1_0)_: ++1 InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_1)_: -+1 InvestmentFlowBlock_old_exo(Source_Bus1_1) +c_e_InvestmentFlowBlock_old_rule_exo(storage_invest_limit_Bus1_1)_: ++1 InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_2)_: -+1 InvestmentFlowBlock_old_exo(Source_Bus1_2) +c_e_InvestmentFlowBlock_old_rule_exo(storage_invest_limit_Bus1_2)_: ++1 InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(Bus1_storage_invest_limit_0)_: @@ -191,6 +179,18 @@ c_e_InvestmentFlowBlock_old_rule_exo(Bus1_storage_invest_limit_2)_: +1 InvestmentFlowBlock_old_exo(Bus1_storage_invest_limit_2) = 0 +c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_0)_: ++1 InvestmentFlowBlock_old_exo(Source_Bus1_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_1)_: ++1 InvestmentFlowBlock_old_exo(Source_Bus1_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(Source_Bus1_2)_: ++1 InvestmentFlowBlock_old_exo(Source_Bus1_2) += 0 + c_e_InvestmentFlowBlock_old_rule(storage_invest_limit_Bus1_0)_: -1 InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_0) -1 InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_0) @@ -209,24 +209,6 @@ c_e_InvestmentFlowBlock_old_rule(storage_invest_limit_Bus1_2)_: -1 InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule(Source_Bus1_0)_: --1 InvestmentFlowBlock_old_end(Source_Bus1_0) --1 InvestmentFlowBlock_old_exo(Source_Bus1_0) -+1 InvestmentFlowBlock_old(Source_Bus1_0) -= 0 - -c_e_InvestmentFlowBlock_old_rule(Source_Bus1_1)_: -+1 InvestmentFlowBlock_old(Source_Bus1_1) --1 InvestmentFlowBlock_old_end(Source_Bus1_1) --1 InvestmentFlowBlock_old_exo(Source_Bus1_1) -= 0 - -c_e_InvestmentFlowBlock_old_rule(Source_Bus1_2)_: -+1 InvestmentFlowBlock_old(Source_Bus1_2) --1 InvestmentFlowBlock_old_end(Source_Bus1_2) --1 InvestmentFlowBlock_old_exo(Source_Bus1_2) -= 0 - c_e_InvestmentFlowBlock_old_rule(Bus1_storage_invest_limit_0)_: -1 InvestmentFlowBlock_old_end(Bus1_storage_invest_limit_0) -1 InvestmentFlowBlock_old_exo(Bus1_storage_invest_limit_0) @@ -245,6 +227,24 @@ c_e_InvestmentFlowBlock_old_rule(Bus1_storage_invest_limit_2)_: -1 InvestmentFlowBlock_old_exo(Bus1_storage_invest_limit_2) = 0 +c_e_InvestmentFlowBlock_old_rule(Source_Bus1_0)_: +-1 InvestmentFlowBlock_old_end(Source_Bus1_0) +-1 InvestmentFlowBlock_old_exo(Source_Bus1_0) ++1 InvestmentFlowBlock_old(Source_Bus1_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(Source_Bus1_1)_: ++1 InvestmentFlowBlock_old(Source_Bus1_1) +-1 InvestmentFlowBlock_old_end(Source_Bus1_1) +-1 InvestmentFlowBlock_old_exo(Source_Bus1_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(Source_Bus1_2)_: ++1 InvestmentFlowBlock_old(Source_Bus1_2) +-1 InvestmentFlowBlock_old_end(Source_Bus1_2) +-1 InvestmentFlowBlock_old_exo(Source_Bus1_2) += 0 + c_u_InvestmentFlowBlock_max(storage_invest_limit_Bus1_0_0)_: +1 flow(storage_invest_limit_Bus1_0_0) -1 InvestmentFlowBlock_total(storage_invest_limit_Bus1_0) @@ -275,36 +275,6 @@ c_u_InvestmentFlowBlock_max(storage_invest_limit_Bus1_2_5)_: -1 InvestmentFlowBlock_total(storage_invest_limit_Bus1_2) <= 0 -c_u_InvestmentFlowBlock_max(Source_Bus1_0_0)_: -+1 flow(Source_Bus1_0_0) --1 InvestmentFlowBlock_total(Source_Bus1_0) -<= 0 - -c_u_InvestmentFlowBlock_max(Source_Bus1_0_1)_: -+1 flow(Source_Bus1_0_1) --1 InvestmentFlowBlock_total(Source_Bus1_0) -<= 0 - -c_u_InvestmentFlowBlock_max(Source_Bus1_1_2)_: -+1 flow(Source_Bus1_1_2) --1 InvestmentFlowBlock_total(Source_Bus1_1) -<= 0 - -c_u_InvestmentFlowBlock_max(Source_Bus1_1_3)_: -+1 flow(Source_Bus1_1_3) --1 InvestmentFlowBlock_total(Source_Bus1_1) -<= 0 - -c_u_InvestmentFlowBlock_max(Source_Bus1_2_4)_: -+1 flow(Source_Bus1_2_4) --1 InvestmentFlowBlock_total(Source_Bus1_2) -<= 0 - -c_u_InvestmentFlowBlock_max(Source_Bus1_2_5)_: -+1 flow(Source_Bus1_2_5) --1 InvestmentFlowBlock_total(Source_Bus1_2) -<= 0 - c_u_InvestmentFlowBlock_max(Bus1_storage_invest_limit_0_0)_: +1 flow(Bus1_storage_invest_limit_0_0) -1 InvestmentFlowBlock_total(Bus1_storage_invest_limit_0) @@ -335,6 +305,36 @@ c_u_InvestmentFlowBlock_max(Bus1_storage_invest_limit_2_5)_: -1 InvestmentFlowBlock_total(Bus1_storage_invest_limit_2) <= 0 +c_u_InvestmentFlowBlock_max(Source_Bus1_0_0)_: ++1 flow(Source_Bus1_0_0) +-1 InvestmentFlowBlock_total(Source_Bus1_0) +<= 0 + +c_u_InvestmentFlowBlock_max(Source_Bus1_0_1)_: ++1 flow(Source_Bus1_0_1) +-1 InvestmentFlowBlock_total(Source_Bus1_0) +<= 0 + +c_u_InvestmentFlowBlock_max(Source_Bus1_1_2)_: ++1 flow(Source_Bus1_1_2) +-1 InvestmentFlowBlock_total(Source_Bus1_1) +<= 0 + +c_u_InvestmentFlowBlock_max(Source_Bus1_1_3)_: ++1 flow(Source_Bus1_1_3) +-1 InvestmentFlowBlock_total(Source_Bus1_1) +<= 0 + +c_u_InvestmentFlowBlock_max(Source_Bus1_2_4)_: ++1 flow(Source_Bus1_2_4) +-1 InvestmentFlowBlock_total(Source_Bus1_2) +<= 0 + +c_u_InvestmentFlowBlock_max(Source_Bus1_2_5)_: ++1 flow(Source_Bus1_2_5) +-1 InvestmentFlowBlock_total(Source_Bus1_2) +<= 0 + c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_invest_limit_0)_: -1 GenericInvestmentStorageBlock_invest(storage_invest_limit_0) +1 GenericInvestmentStorageBlock_total(storage_invest_limit_0) @@ -528,11 +528,6 @@ bounds 0 <= InvestmentFlowBlock_total(storage_invest_limit_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_invest(storage_invest_limit_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old(storage_invest_limit_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_total(Source_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_total(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_old(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_total(Source_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_total(Bus1_storage_invest_limit_0) <= +inf 0 <= InvestmentFlowBlock_invest(Bus1_storage_invest_limit_0) <= +inf 0 <= InvestmentFlowBlock_total(Bus1_storage_invest_limit_1) <= +inf @@ -541,27 +536,32 @@ bounds 0 <= InvestmentFlowBlock_total(Bus1_storage_invest_limit_2) <= +inf 0 <= InvestmentFlowBlock_invest(Bus1_storage_invest_limit_2) <= +inf 0 <= InvestmentFlowBlock_old(Bus1_storage_invest_limit_2) <= +inf + 0 <= InvestmentFlowBlock_total(Source_Bus1_0) <= +inf + 0 <= InvestmentFlowBlock_total(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_old(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_total(Source_Bus1_2) <= +inf + 0 <= InvestmentFlowBlock_old(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_0) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_1) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_invest_limit_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(Source_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old_end(Bus1_storage_invest_limit_0) <= +inf 0 <= InvestmentFlowBlock_old_end(Bus1_storage_invest_limit_1) <= +inf 0 <= InvestmentFlowBlock_old_end(Bus1_storage_invest_limit_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(Source_Bus1_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_invest_limit_Bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_invest_limit_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_invest_limit_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(Bus1_storage_invest_limit_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(Source_Bus1_2) <= +inf 0 <= InvestmentFlowBlock_old(storage_invest_limit_Bus1_0) <= +inf - 0 <= InvestmentFlowBlock_old(Source_Bus1_0) <= +inf 0 <= InvestmentFlowBlock_old(Bus1_storage_invest_limit_0) <= +inf + 0 <= InvestmentFlowBlock_old(Source_Bus1_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_invest_limit_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_invest_limit_1) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage_invest_limit_1) <= +inf diff --git a/tests/lp_files/periodical_investment_limit_with_dsm_DIW.lp b/tests/lp_files/periodical_investment_limit_with_dsm_DIW.lp index 28e220674..1fe4aaa5c 100644 --- a/tests/lp_files/periodical_investment_limit_with_dsm_DIW.lp +++ b/tests/lp_files/periodical_investment_limit_with_dsm_DIW.lp @@ -2,9 +2,9 @@ min objective: -+285.3937455128117 InvestmentFlowBlock_invest(Source_Bus1_0) -+279.7977897184428 InvestmentFlowBlock_invest(Source_Bus1_1) -+274.31155854749295 InvestmentFlowBlock_invest(Source_Bus1_2) ++8.230422488026955 InvestmentFlowBlock_invest(Source_Bus1_0) ++5.432444590842506 InvestmentFlowBlock_invest(Source_Bus1_1) ++2.6893290053675805 InvestmentFlowBlock_invest(Source_Bus1_2) +0.5 SinkDSMDIWInvestmentBlock_dsm_do_shift(sink_dsm_DIW_0_0) +0.5 SinkDSMDIWInvestmentBlock_dsm_do_shift(sink_dsm_DIW_1_0) +0.5 SinkDSMDIWInvestmentBlock_dsm_do_shift(sink_dsm_DIW_2_0) @@ -47,25 +47,25 @@ objective: +0.48058439061899266 SinkDSMDIWInvestmentBlock_dsm_do_shift(sink_dsm_DIW_3_5) +0.48058439061899266 SinkDSMDIWInvestmentBlock_dsm_do_shift(sink_dsm_DIW_4_5) +0.48058439061899266 SinkDSMDIWInvestmentBlock_dsm_do_shift(sink_dsm_DIW_5_5) -+103.00990099009903 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_0) -+100.990099009901 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_1) -+99.00990099009901 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_2) ++99.99999999999999 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_0) ++98.03921568627449 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_1) ++48.534265191225046 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_2) s.t. c_u_investment_limit_per_period(0)_: -+285.3937455128117 InvestmentFlowBlock_invest(Source_Bus1_0) -+103.00990099009903 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_0) ++8.230422488026955 InvestmentFlowBlock_invest(Source_Bus1_0) ++99.99999999999999 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_0) <= 400 c_u_investment_limit_per_period(1)_: -+279.7977897184428 InvestmentFlowBlock_invest(Source_Bus1_1) -+100.990099009901 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_1) ++5.432444590842506 InvestmentFlowBlock_invest(Source_Bus1_1) ++98.03921568627449 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_1) <= 300 c_u_investment_limit_per_period(2)_: -+274.31155854749295 InvestmentFlowBlock_invest(Source_Bus1_2) -+99.00990099009901 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_2) ++2.6893290053675805 InvestmentFlowBlock_invest(Source_Bus1_2) ++48.534265191225046 SinkDSMDIWInvestmentBlock_invest(sink_dsm_DIW_2) <= 200 c_e_BusBlock_balance(Bus1_0_0)_: diff --git a/tests/lp_files/periodical_investment_limit_with_dsm_DLR.lp b/tests/lp_files/periodical_investment_limit_with_dsm_DLR.lp index 5f697ad19..3d3d8a7d3 100644 --- a/tests/lp_files/periodical_investment_limit_with_dsm_DLR.lp +++ b/tests/lp_files/periodical_investment_limit_with_dsm_DLR.lp @@ -2,9 +2,9 @@ min objective: -+285.3937455128117 InvestmentFlowBlock_invest(Source_Bus1_0) -+279.7977897184428 InvestmentFlowBlock_invest(Source_Bus1_1) -+274.31155854749295 InvestmentFlowBlock_invest(Source_Bus1_2) ++8.230422488026955 InvestmentFlowBlock_invest(Source_Bus1_0) ++5.432444590842506 InvestmentFlowBlock_invest(Source_Bus1_1) ++2.6893290053675805 InvestmentFlowBlock_invest(Source_Bus1_2) +0.5 SinkDSMDLRInvestmentBlock_dsm_do_shift(sink_dsm_DLR_1_0) +0.5 SinkDSMDLRInvestmentBlock_balance_dsm_up(sink_dsm_DLR_1_0) +0.5 SinkDSMDLRInvestmentBlock_dsm_up(sink_dsm_DLR_1_0) @@ -29,25 +29,25 @@ objective: +0.48058439061899266 SinkDSMDLRInvestmentBlock_balance_dsm_do(sink_dsm_DLR_1_5) +0.48058439061899266 SinkDSMDLRInvestmentBlock_dsm_do_shift(sink_dsm_DLR_1_5) +0.48058439061899266 SinkDSMDLRInvestmentBlock_balance_dsm_up(sink_dsm_DLR_1_5) -+103.00990099009903 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_0) -+100.990099009901 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_1) -+99.00990099009901 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_2) ++99.99999999999999 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_0) ++98.03921568627449 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_1) ++48.534265191225046 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_2) s.t. c_u_investment_limit_per_period(0)_: -+285.3937455128117 InvestmentFlowBlock_invest(Source_Bus1_0) -+103.00990099009903 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_0) ++8.230422488026955 InvestmentFlowBlock_invest(Source_Bus1_0) ++99.99999999999999 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_0) <= 400 c_u_investment_limit_per_period(1)_: -+279.7977897184428 InvestmentFlowBlock_invest(Source_Bus1_1) -+100.990099009901 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_1) ++5.432444590842506 InvestmentFlowBlock_invest(Source_Bus1_1) ++98.03921568627449 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_1) <= 300 c_u_investment_limit_per_period(2)_: -+274.31155854749295 InvestmentFlowBlock_invest(Source_Bus1_2) -+99.00990099009901 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_2) ++2.6893290053675805 InvestmentFlowBlock_invest(Source_Bus1_2) ++48.534265191225046 SinkDSMDLRInvestmentBlock_invest(sink_dsm_DLR_2) <= 200 c_e_BusBlock_balance(Bus1_0_0)_: diff --git a/tests/lp_files/periodical_investment_limit_with_dsm_oemof.lp b/tests/lp_files/periodical_investment_limit_with_dsm_oemof.lp index f1961322c..342026442 100644 --- a/tests/lp_files/periodical_investment_limit_with_dsm_oemof.lp +++ b/tests/lp_files/periodical_investment_limit_with_dsm_oemof.lp @@ -2,9 +2,9 @@ min objective: -+285.3937455128117 InvestmentFlowBlock_invest(Source_Bus1_0) -+279.7977897184428 InvestmentFlowBlock_invest(Source_Bus1_1) -+274.31155854749295 InvestmentFlowBlock_invest(Source_Bus1_2) ++8.230422488026955 InvestmentFlowBlock_invest(Source_Bus1_0) ++5.432444590842506 InvestmentFlowBlock_invest(Source_Bus1_1) ++2.6893290053675805 InvestmentFlowBlock_invest(Source_Bus1_2) +0.5 SinkDSMOemofInvestmentBlock_dsm_do_shift(sink_dsm_oemof_0) +0.5 SinkDSMOemofInvestmentBlock_dsm_up(sink_dsm_oemof_0) +0.5 SinkDSMOemofInvestmentBlock_dsm_up(sink_dsm_oemof_1) @@ -17,25 +17,25 @@ objective: +0.48058439061899266 SinkDSMOemofInvestmentBlock_dsm_do_shift(sink_dsm_oemof_4) +0.48058439061899266 SinkDSMOemofInvestmentBlock_dsm_up(sink_dsm_oemof_5) +0.48058439061899266 SinkDSMOemofInvestmentBlock_dsm_do_shift(sink_dsm_oemof_5) -+103.00990099009903 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_0) -+100.990099009901 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_1) -+99.00990099009901 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_2) ++99.99999999999999 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_0) ++98.03921568627449 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_1) ++48.534265191225046 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_2) s.t. c_u_investment_limit_per_period(0)_: -+285.3937455128117 InvestmentFlowBlock_invest(Source_Bus1_0) -+103.00990099009903 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_0) ++8.230422488026955 InvestmentFlowBlock_invest(Source_Bus1_0) ++99.99999999999999 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_0) <= 400 c_u_investment_limit_per_period(1)_: -+279.7977897184428 InvestmentFlowBlock_invest(Source_Bus1_1) -+100.990099009901 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_1) ++5.432444590842506 InvestmentFlowBlock_invest(Source_Bus1_1) ++98.03921568627449 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_1) <= 300 c_u_investment_limit_per_period(2)_: -+274.31155854749295 InvestmentFlowBlock_invest(Source_Bus1_2) -+99.00990099009901 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_2) ++2.6893290053675805 InvestmentFlowBlock_invest(Source_Bus1_2) ++48.534265191225046 SinkDSMOemofInvestmentBlock_invest(sink_dsm_oemof_2) <= 200 c_e_BusBlock_balance(Bus1_0_0)_: diff --git a/tests/lp_files/storage_invest_1_multi_period.lp b/tests/lp_files/storage_invest_1_multi_period.lp index 35c7ff688..05d3dcf67 100644 --- a/tests/lp_files/storage_invest_1_multi_period.lp +++ b/tests/lp_files/storage_invest_1_multi_period.lp @@ -14,9 +14,9 @@ objective: +23.52941176470588 flow(storage1_electricityBus_1_3) +23.06805074971165 flow(storage1_electricityBus_2_4) +23.06805074971165 flow(storage1_electricityBus_2_5) -+232.70350285300475 GenericInvestmentStorageBlock_invest(storage1_0) -+228.14068907157326 GenericInvestmentStorageBlock_invest(storage1_1) -+223.6673422270326 GenericInvestmentStorageBlock_invest(storage1_2) ++33.55448696821628 GenericInvestmentStorageBlock_invest(storage1_0) ++22.14745251463754 GenericInvestmentStorageBlock_invest(storage1_1) ++10.964085403285921 GenericInvestmentStorageBlock_invest(storage1_2) s.t. @@ -50,25 +50,6 @@ c_e_BusBlock_balance(electricityBus_2_5)_: +1 flow(storage1_electricityBus_2_5) = 0 -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_0)_: -+1 InvestmentFlowBlock_total(electricityBus_storage1_0) --1 InvestmentFlowBlock_invest(electricityBus_storage1_0) -= 0 - -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_1)_: --1 InvestmentFlowBlock_total(electricityBus_storage1_0) -+1 InvestmentFlowBlock_total(electricityBus_storage1_1) --1 InvestmentFlowBlock_invest(electricityBus_storage1_1) -+1 InvestmentFlowBlock_old(electricityBus_storage1_1) -= 0 - -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_2)_: --1 InvestmentFlowBlock_total(electricityBus_storage1_1) -+1 InvestmentFlowBlock_total(electricityBus_storage1_2) --1 InvestmentFlowBlock_invest(electricityBus_storage1_2) -+1 InvestmentFlowBlock_old(electricityBus_storage1_2) -= 0 - c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_0)_: +1 InvestmentFlowBlock_total(storage1_electricityBus_0) -1 InvestmentFlowBlock_invest(storage1_electricityBus_0) @@ -88,16 +69,23 @@ c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_2)_: +1 InvestmentFlowBlock_old(storage1_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_0)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage1_0) +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_0)_: ++1 InvestmentFlowBlock_total(electricityBus_storage1_0) +-1 InvestmentFlowBlock_invest(electricityBus_storage1_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_1)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage1_1) +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_1)_: +-1 InvestmentFlowBlock_total(electricityBus_storage1_0) ++1 InvestmentFlowBlock_total(electricityBus_storage1_1) +-1 InvestmentFlowBlock_invest(electricityBus_storage1_1) ++1 InvestmentFlowBlock_old(electricityBus_storage1_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_2)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage1_2) +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_2)_: +-1 InvestmentFlowBlock_total(electricityBus_storage1_1) ++1 InvestmentFlowBlock_total(electricityBus_storage1_2) +-1 InvestmentFlowBlock_invest(electricityBus_storage1_2) ++1 InvestmentFlowBlock_old(electricityBus_storage1_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_0)_: @@ -112,16 +100,16 @@ c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_2)_: +1 InvestmentFlowBlock_old_end(storage1_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_0)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage1_0) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_0)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage1_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_1)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage1_1) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_1)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage1_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_2)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage1_2) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_2)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage1_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_0)_: @@ -136,22 +124,16 @@ c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_2)_: +1 InvestmentFlowBlock_old_exo(storage1_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_0)_: --1 InvestmentFlowBlock_old_end(electricityBus_storage1_0) --1 InvestmentFlowBlock_old_exo(electricityBus_storage1_0) -+1 InvestmentFlowBlock_old(electricityBus_storage1_0) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_0)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage1_0) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_1)_: -+1 InvestmentFlowBlock_old(electricityBus_storage1_1) --1 InvestmentFlowBlock_old_end(electricityBus_storage1_1) --1 InvestmentFlowBlock_old_exo(electricityBus_storage1_1) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_1)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage1_1) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_2)_: -+1 InvestmentFlowBlock_old(electricityBus_storage1_2) --1 InvestmentFlowBlock_old_end(electricityBus_storage1_2) --1 InvestmentFlowBlock_old_exo(electricityBus_storage1_2) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_2)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage1_2) = 0 c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_0)_: @@ -172,35 +154,23 @@ c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_2)_: -1 InvestmentFlowBlock_old_exo(storage1_electricityBus_2) = 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage1_0_0)_: -+1 flow(electricityBus_storage1_0_0) --1 InvestmentFlowBlock_total(electricityBus_storage1_0) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage1_0_1)_: -+1 flow(electricityBus_storage1_0_1) --1 InvestmentFlowBlock_total(electricityBus_storage1_0) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage1_1_2)_: -+1 flow(electricityBus_storage1_1_2) --1 InvestmentFlowBlock_total(electricityBus_storage1_1) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage1_1_3)_: -+1 flow(electricityBus_storage1_1_3) --1 InvestmentFlowBlock_total(electricityBus_storage1_1) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_0)_: +-1 InvestmentFlowBlock_old_end(electricityBus_storage1_0) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage1_0) ++1 InvestmentFlowBlock_old(electricityBus_storage1_0) += 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage1_2_4)_: -+1 flow(electricityBus_storage1_2_4) --1 InvestmentFlowBlock_total(electricityBus_storage1_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_1)_: ++1 InvestmentFlowBlock_old(electricityBus_storage1_1) +-1 InvestmentFlowBlock_old_end(electricityBus_storage1_1) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage1_1) += 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage1_2_5)_: -+1 flow(electricityBus_storage1_2_5) --1 InvestmentFlowBlock_total(electricityBus_storage1_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_2)_: ++1 InvestmentFlowBlock_old(electricityBus_storage1_2) +-1 InvestmentFlowBlock_old_end(electricityBus_storage1_2) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage1_2) += 0 c_u_InvestmentFlowBlock_max(storage1_electricityBus_0_0)_: +1 flow(storage1_electricityBus_0_0) @@ -232,6 +202,36 @@ c_u_InvestmentFlowBlock_max(storage1_electricityBus_2_5)_: -1 InvestmentFlowBlock_total(storage1_electricityBus_2) <= 0 +c_u_InvestmentFlowBlock_max(electricityBus_storage1_0_0)_: ++1 flow(electricityBus_storage1_0_0) +-1 InvestmentFlowBlock_total(electricityBus_storage1_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_0_1)_: ++1 flow(electricityBus_storage1_0_1) +-1 InvestmentFlowBlock_total(electricityBus_storage1_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_1_2)_: ++1 flow(electricityBus_storage1_1_2) +-1 InvestmentFlowBlock_total(electricityBus_storage1_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_1_3)_: ++1 flow(electricityBus_storage1_1_3) +-1 InvestmentFlowBlock_total(electricityBus_storage1_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_2_4)_: ++1 flow(electricityBus_storage1_2_4) +-1 InvestmentFlowBlock_total(electricityBus_storage1_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_2_5)_: ++1 flow(electricityBus_storage1_2_5) +-1 InvestmentFlowBlock_total(electricityBus_storage1_2) +<= 0 + c_e_GenericInvestmentStorageBlock_total_storage_rule(storage1_0)_: -1 GenericInvestmentStorageBlock_invest(storage1_0) +1 GenericInvestmentStorageBlock_total(storage1_0) @@ -454,14 +454,6 @@ bounds 0 <= GenericInvestmentStorageBlock_invest(storage1_0) <= 234 0 <= GenericInvestmentStorageBlock_invest(storage1_1) <= 234 0 <= GenericInvestmentStorageBlock_invest(storage1_2) <= 234 - 0 <= InvestmentFlowBlock_total(electricityBus_storage1_0) <= +inf - 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_0) <= +inf - 0 <= InvestmentFlowBlock_total(electricityBus_storage1_1) <= +inf - 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_1) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage1_1) <= +inf - 0 <= InvestmentFlowBlock_total(electricityBus_storage1_2) <= +inf - 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_2) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage1_2) <= +inf 0 <= InvestmentFlowBlock_total(storage1_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_total(storage1_electricityBus_1) <= +inf @@ -470,20 +462,28 @@ bounds 0 <= InvestmentFlowBlock_total(storage1_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old(storage1_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage1_2) <= +inf 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_2) <= +inf 0 <= InvestmentFlowBlock_old(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage1_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage1_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage1_1) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage1_1) <= +inf diff --git a/tests/lp_files/storage_invest_2_multi_period.lp b/tests/lp_files/storage_invest_2_multi_period.lp index 2331318ef..816985cb6 100644 --- a/tests/lp_files/storage_invest_2_multi_period.lp +++ b/tests/lp_files/storage_invest_2_multi_period.lp @@ -2,15 +2,15 @@ min objective: -+121.09030188807486 InvestmentFlowBlock_invest(electricityBus_storage2_0) -+118.71598224321065 InvestmentFlowBlock_invest(electricityBus_storage2_1) -+116.38821788550062 InvestmentFlowBlock_invest(electricityBus_storage2_2) -+11.00820926255226 InvestmentFlowBlock_invest(storage2_electricityBus_0) -+10.792362022110058 InvestmentFlowBlock_invest(storage2_electricityBus_1) -+10.580747080500057 InvestmentFlowBlock_invest(storage2_electricityBus_2) -+177.35448256334197 GenericInvestmentStorageBlock_invest(storage2_0) -+173.87694368955096 GenericInvestmentStorageBlock_invest(storage2_1) -+170.46759185250093 GenericInvestmentStorageBlock_invest(storage2_2) ++1.5873195277040417 InvestmentFlowBlock_invest(storage2_electricityBus_0) ++1.0477014265985347 InvestmentFlowBlock_invest(storage2_electricityBus_1) ++0.5186640725735326 InvestmentFlowBlock_invest(storage2_electricityBus_2) ++17.46051480474446 InvestmentFlowBlock_invest(electricityBus_storage2_0) ++11.524715692583884 InvestmentFlowBlock_invest(electricityBus_storage2_1) ++5.705304798308859 InvestmentFlowBlock_invest(electricityBus_storage2_2) ++25.57348127967623 GenericInvestmentStorageBlock_invest(storage2_0) ++16.879634095198618 GenericInvestmentStorageBlock_invest(storage2_1) ++8.35625450257358 GenericInvestmentStorageBlock_invest(storage2_2) s.t. @@ -44,25 +44,6 @@ c_e_BusBlock_balance(electricityBus_2_5)_: -1 flow(electricityBus_storage2_2_5) = 0 -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage2_0)_: --1 InvestmentFlowBlock_invest(electricityBus_storage2_0) -+1 InvestmentFlowBlock_total(electricityBus_storage2_0) -= 0 - -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage2_1)_: --1 InvestmentFlowBlock_invest(electricityBus_storage2_1) --1 InvestmentFlowBlock_total(electricityBus_storage2_0) -+1 InvestmentFlowBlock_total(electricityBus_storage2_1) -+1 InvestmentFlowBlock_old(electricityBus_storage2_1) -= 0 - -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage2_2)_: --1 InvestmentFlowBlock_invest(electricityBus_storage2_2) --1 InvestmentFlowBlock_total(electricityBus_storage2_1) -+1 InvestmentFlowBlock_total(electricityBus_storage2_2) -+1 InvestmentFlowBlock_old(electricityBus_storage2_2) -= 0 - c_e_InvestmentFlowBlock_total_rule(storage2_electricityBus_0)_: -1 InvestmentFlowBlock_invest(storage2_electricityBus_0) +1 InvestmentFlowBlock_total(storage2_electricityBus_0) @@ -82,16 +63,23 @@ c_e_InvestmentFlowBlock_total_rule(storage2_electricityBus_2)_: +1 InvestmentFlowBlock_old(storage2_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage2_0)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage2_0) +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage2_0)_: +-1 InvestmentFlowBlock_invest(electricityBus_storage2_0) ++1 InvestmentFlowBlock_total(electricityBus_storage2_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage2_1)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage2_1) +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage2_1)_: +-1 InvestmentFlowBlock_invest(electricityBus_storage2_1) +-1 InvestmentFlowBlock_total(electricityBus_storage2_0) ++1 InvestmentFlowBlock_total(electricityBus_storage2_1) ++1 InvestmentFlowBlock_old(electricityBus_storage2_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage2_2)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage2_2) +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage2_2)_: +-1 InvestmentFlowBlock_invest(electricityBus_storage2_2) +-1 InvestmentFlowBlock_total(electricityBus_storage2_1) ++1 InvestmentFlowBlock_total(electricityBus_storage2_2) ++1 InvestmentFlowBlock_old(electricityBus_storage2_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(storage2_electricityBus_0)_: @@ -106,16 +94,16 @@ c_e_InvestmentFlowBlock_old_rule_end(storage2_electricityBus_2)_: +1 InvestmentFlowBlock_old_end(storage2_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage2_0)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage2_0) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage2_0)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage2_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage2_1)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage2_1) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage2_1)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage2_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage2_2)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage2_2) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage2_2)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage2_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(storage2_electricityBus_0)_: @@ -130,22 +118,16 @@ c_e_InvestmentFlowBlock_old_rule_exo(storage2_electricityBus_2)_: +1 InvestmentFlowBlock_old_exo(storage2_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage2_0)_: --1 InvestmentFlowBlock_old_end(electricityBus_storage2_0) --1 InvestmentFlowBlock_old_exo(electricityBus_storage2_0) -+1 InvestmentFlowBlock_old(electricityBus_storage2_0) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage2_0)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage2_0) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage2_1)_: -+1 InvestmentFlowBlock_old(electricityBus_storage2_1) --1 InvestmentFlowBlock_old_end(electricityBus_storage2_1) --1 InvestmentFlowBlock_old_exo(electricityBus_storage2_1) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage2_1)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage2_1) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage2_2)_: -+1 InvestmentFlowBlock_old(electricityBus_storage2_2) --1 InvestmentFlowBlock_old_end(electricityBus_storage2_2) --1 InvestmentFlowBlock_old_exo(electricityBus_storage2_2) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage2_2)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage2_2) = 0 c_e_InvestmentFlowBlock_old_rule(storage2_electricityBus_0)_: @@ -166,35 +148,23 @@ c_e_InvestmentFlowBlock_old_rule(storage2_electricityBus_2)_: -1 InvestmentFlowBlock_old_exo(storage2_electricityBus_2) = 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage2_0_0)_: -+1 flow(electricityBus_storage2_0_0) --1 InvestmentFlowBlock_total(electricityBus_storage2_0) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage2_0_1)_: -+1 flow(electricityBus_storage2_0_1) --1 InvestmentFlowBlock_total(electricityBus_storage2_0) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage2_1_2)_: -+1 flow(electricityBus_storage2_1_2) --1 InvestmentFlowBlock_total(electricityBus_storage2_1) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage2_1_3)_: -+1 flow(electricityBus_storage2_1_3) --1 InvestmentFlowBlock_total(electricityBus_storage2_1) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage2_0)_: +-1 InvestmentFlowBlock_old_end(electricityBus_storage2_0) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage2_0) ++1 InvestmentFlowBlock_old(electricityBus_storage2_0) += 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage2_2_4)_: -+1 flow(electricityBus_storage2_2_4) --1 InvestmentFlowBlock_total(electricityBus_storage2_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage2_1)_: ++1 InvestmentFlowBlock_old(electricityBus_storage2_1) +-1 InvestmentFlowBlock_old_end(electricityBus_storage2_1) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage2_1) += 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage2_2_5)_: -+1 flow(electricityBus_storage2_2_5) --1 InvestmentFlowBlock_total(electricityBus_storage2_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage2_2)_: ++1 InvestmentFlowBlock_old(electricityBus_storage2_2) +-1 InvestmentFlowBlock_old_end(electricityBus_storage2_2) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage2_2) += 0 c_u_InvestmentFlowBlock_max(storage2_electricityBus_0_0)_: +1 flow(storage2_electricityBus_0_0) @@ -226,6 +196,36 @@ c_u_InvestmentFlowBlock_max(storage2_electricityBus_2_5)_: -1 InvestmentFlowBlock_total(storage2_electricityBus_2) <= 0 +c_u_InvestmentFlowBlock_max(electricityBus_storage2_0_0)_: ++1 flow(electricityBus_storage2_0_0) +-1 InvestmentFlowBlock_total(electricityBus_storage2_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage2_0_1)_: ++1 flow(electricityBus_storage2_0_1) +-1 InvestmentFlowBlock_total(electricityBus_storage2_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage2_1_2)_: ++1 flow(electricityBus_storage2_1_2) +-1 InvestmentFlowBlock_total(electricityBus_storage2_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage2_1_3)_: ++1 flow(electricityBus_storage2_1_3) +-1 InvestmentFlowBlock_total(electricityBus_storage2_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage2_2_4)_: ++1 flow(electricityBus_storage2_2_4) +-1 InvestmentFlowBlock_total(electricityBus_storage2_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage2_2_5)_: ++1 flow(electricityBus_storage2_2_5) +-1 InvestmentFlowBlock_total(electricityBus_storage2_2) +<= 0 + c_e_GenericInvestmentStorageBlock_total_storage_rule(storage2_0)_: -1 GenericInvestmentStorageBlock_invest(storage2_0) +1 GenericInvestmentStorageBlock_total(storage2_0) @@ -357,12 +357,12 @@ c_u_GenericInvestmentStorageBlock_max_storage_content(storage2_2_5)_: <= 0 bounds - 0 <= InvestmentFlowBlock_invest(electricityBus_storage2_0) <= +inf - 0 <= InvestmentFlowBlock_invest(electricityBus_storage2_1) <= +inf - 0 <= InvestmentFlowBlock_invest(electricityBus_storage2_2) <= +inf 0 <= InvestmentFlowBlock_invest(storage2_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_invest(storage2_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_invest(storage2_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage2_0) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage2_1) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage2_2) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage2_0) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage2_1) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage2_2) <= +inf @@ -378,30 +378,30 @@ bounds 0 <= flow(electricityBus_storage2_2_4) <= +inf 0 <= flow(storage2_electricityBus_2_5) <= +inf 0 <= flow(electricityBus_storage2_2_5) <= +inf - 0 <= InvestmentFlowBlock_total(electricityBus_storage2_0) <= +inf - 0 <= InvestmentFlowBlock_total(electricityBus_storage2_1) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage2_1) <= +inf - 0 <= InvestmentFlowBlock_total(electricityBus_storage2_2) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage2_2) <= +inf 0 <= InvestmentFlowBlock_total(storage2_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_total(storage2_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old(storage2_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_total(storage2_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old(storage2_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage2_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage2_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage2_2) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage2_0) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage2_1) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage2_1) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage2_2) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage2_2) <= +inf 0 <= InvestmentFlowBlock_old_end(storage2_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_old_end(storage2_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old_end(storage2_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage2_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage2_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage2_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage2_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage2_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage2_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage2_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage2_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage2_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage2_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage2_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage2_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage2_2) <= +inf 0 <= InvestmentFlowBlock_old(storage2_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage2_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage2_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage2_1) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage2_1) <= +inf diff --git a/tests/lp_files/storage_invest_3_multi_period.lp b/tests/lp_files/storage_invest_3_multi_period.lp index 2fc9750d0..f5646972e 100644 --- a/tests/lp_files/storage_invest_3_multi_period.lp +++ b/tests/lp_files/storage_invest_3_multi_period.lp @@ -2,12 +2,12 @@ min objective: -+101.97980198019803 InvestmentFlowBlock_invest(electricityBus_storage3_0) -+99.98019801980199 InvestmentFlowBlock_invest(electricityBus_storage3_1) -+98.01980198019803 InvestmentFlowBlock_invest(electricityBus_storage3_2) -+11.00820926255226 InvestmentFlowBlock_invest(storage3_electricityBus_0) -+10.792362022110058 InvestmentFlowBlock_invest(storage3_electricityBus_1) -+10.580747080500057 InvestmentFlowBlock_invest(storage3_electricityBus_2) ++98.99999999999999 InvestmentFlowBlock_invest(electricityBus_storage3_0) ++97.05882352941174 InvestmentFlowBlock_invest(electricityBus_storage3_1) ++48.0489225393128 InvestmentFlowBlock_invest(electricityBus_storage3_2) ++1.5873195277040417 InvestmentFlowBlock_invest(storage3_electricityBus_0) ++1.0477014265985347 InvestmentFlowBlock_invest(storage3_electricityBus_1) ++0.5186640725735326 InvestmentFlowBlock_invest(storage3_electricityBus_2) s.t. diff --git a/tests/lp_files/storage_invest_4_multi_period.lp b/tests/lp_files/storage_invest_4_multi_period.lp index c391c9b46..c08305a40 100644 --- a/tests/lp_files/storage_invest_4_multi_period.lp +++ b/tests/lp_files/storage_invest_4_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+149.3643564356436 GenericInvestmentStorageBlock_invest(storage4_0) -+146.43564356435647 GenericInvestmentStorageBlock_invest(storage4_1) -+143.5643564356436 GenericInvestmentStorageBlock_invest(storage4_2) ++145.0 GenericInvestmentStorageBlock_invest(storage4_0) ++142.15686274509804 GenericInvestmentStorageBlock_invest(storage4_1) ++70.37468452727633 GenericInvestmentStorageBlock_invest(storage4_2) s.t. diff --git a/tests/lp_files/storage_invest_5_multi_period.lp b/tests/lp_files/storage_invest_5_multi_period.lp index db88b35f0..e139e72db 100644 --- a/tests/lp_files/storage_invest_5_multi_period.lp +++ b/tests/lp_files/storage_invest_5_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+121.09030188807486 InvestmentFlowBlock_invest(electricityBus_storage5_0) -+118.71598224321065 InvestmentFlowBlock_invest(electricityBus_storage5_1) -+116.38821788550062 InvestmentFlowBlock_invest(electricityBus_storage5_2) ++17.46051480474446 InvestmentFlowBlock_invest(electricityBus_storage5_0) ++11.524715692583884 InvestmentFlowBlock_invest(electricityBus_storage5_1) ++5.705304798308859 InvestmentFlowBlock_invest(electricityBus_storage5_2) s.t. @@ -38,25 +38,6 @@ c_e_BusBlock_balance(electricityBus_2_5)_: -1 flow(electricityBus_storage5_2_5) = 0 -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage5_0)_: --1 InvestmentFlowBlock_invest(electricityBus_storage5_0) -+1 InvestmentFlowBlock_total(electricityBus_storage5_0) -= 110 - -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage5_1)_: --1 InvestmentFlowBlock_invest(electricityBus_storage5_1) --1 InvestmentFlowBlock_total(electricityBus_storage5_0) -+1 InvestmentFlowBlock_total(electricityBus_storage5_1) -+1 InvestmentFlowBlock_old(electricityBus_storage5_1) -= 0 - -c_e_InvestmentFlowBlock_total_rule(electricityBus_storage5_2)_: --1 InvestmentFlowBlock_invest(electricityBus_storage5_2) --1 InvestmentFlowBlock_total(electricityBus_storage5_1) -+1 InvestmentFlowBlock_total(electricityBus_storage5_2) -+1 InvestmentFlowBlock_old(electricityBus_storage5_2) -= 0 - c_e_InvestmentFlowBlock_total_rule(storage5_electricityBus_0)_: +1 InvestmentFlowBlock_total(storage5_electricityBus_0) -1 InvestmentFlowBlock_invest(storage5_electricityBus_0) @@ -76,16 +57,23 @@ c_e_InvestmentFlowBlock_total_rule(storage5_electricityBus_2)_: +1 InvestmentFlowBlock_old(storage5_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage5_0)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage5_0) -= 0 +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage5_0)_: +-1 InvestmentFlowBlock_invest(electricityBus_storage5_0) ++1 InvestmentFlowBlock_total(electricityBus_storage5_0) += 110 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage5_1)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage5_1) +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage5_1)_: +-1 InvestmentFlowBlock_invest(electricityBus_storage5_1) +-1 InvestmentFlowBlock_total(electricityBus_storage5_0) ++1 InvestmentFlowBlock_total(electricityBus_storage5_1) ++1 InvestmentFlowBlock_old(electricityBus_storage5_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage5_2)_: -+1 InvestmentFlowBlock_old_end(electricityBus_storage5_2) +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage5_2)_: +-1 InvestmentFlowBlock_invest(electricityBus_storage5_2) +-1 InvestmentFlowBlock_total(electricityBus_storage5_1) ++1 InvestmentFlowBlock_total(electricityBus_storage5_2) ++1 InvestmentFlowBlock_old(electricityBus_storage5_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(storage5_electricityBus_0)_: @@ -100,16 +88,16 @@ c_e_InvestmentFlowBlock_old_rule_end(storage5_electricityBus_2)_: +1 InvestmentFlowBlock_old_end(storage5_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage5_0)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage5_0) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage5_0)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage5_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage5_1)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage5_1) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage5_1)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage5_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage5_2)_: -+1 InvestmentFlowBlock_old_exo(electricityBus_storage5_2) +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage5_2)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage5_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(storage5_electricityBus_0)_: @@ -124,22 +112,16 @@ c_e_InvestmentFlowBlock_old_rule_exo(storage5_electricityBus_2)_: +1 InvestmentFlowBlock_old_exo(storage5_electricityBus_2) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage5_0)_: --1 InvestmentFlowBlock_old_end(electricityBus_storage5_0) --1 InvestmentFlowBlock_old_exo(electricityBus_storage5_0) -+1 InvestmentFlowBlock_old(electricityBus_storage5_0) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage5_0)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage5_0) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage5_1)_: -+1 InvestmentFlowBlock_old(electricityBus_storage5_1) --1 InvestmentFlowBlock_old_end(electricityBus_storage5_1) --1 InvestmentFlowBlock_old_exo(electricityBus_storage5_1) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage5_1)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage5_1) = 0 -c_e_InvestmentFlowBlock_old_rule(electricityBus_storage5_2)_: -+1 InvestmentFlowBlock_old(electricityBus_storage5_2) --1 InvestmentFlowBlock_old_end(electricityBus_storage5_2) --1 InvestmentFlowBlock_old_exo(electricityBus_storage5_2) +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage5_2)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage5_2) = 0 c_e_InvestmentFlowBlock_old_rule(storage5_electricityBus_0)_: @@ -160,35 +142,23 @@ c_e_InvestmentFlowBlock_old_rule(storage5_electricityBus_2)_: -1 InvestmentFlowBlock_old_exo(storage5_electricityBus_2) = 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage5_0_0)_: -+1 flow(electricityBus_storage5_0_0) --1 InvestmentFlowBlock_total(electricityBus_storage5_0) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage5_0_1)_: -+1 flow(electricityBus_storage5_0_1) --1 InvestmentFlowBlock_total(electricityBus_storage5_0) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage5_1_2)_: -+1 flow(electricityBus_storage5_1_2) --1 InvestmentFlowBlock_total(electricityBus_storage5_1) -<= 0 - -c_u_InvestmentFlowBlock_max(electricityBus_storage5_1_3)_: -+1 flow(electricityBus_storage5_1_3) --1 InvestmentFlowBlock_total(electricityBus_storage5_1) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage5_0)_: +-1 InvestmentFlowBlock_old_end(electricityBus_storage5_0) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage5_0) ++1 InvestmentFlowBlock_old(electricityBus_storage5_0) += 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage5_2_4)_: -+1 flow(electricityBus_storage5_2_4) --1 InvestmentFlowBlock_total(electricityBus_storage5_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage5_1)_: ++1 InvestmentFlowBlock_old(electricityBus_storage5_1) +-1 InvestmentFlowBlock_old_end(electricityBus_storage5_1) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage5_1) += 0 -c_u_InvestmentFlowBlock_max(electricityBus_storage5_2_5)_: -+1 flow(electricityBus_storage5_2_5) --1 InvestmentFlowBlock_total(electricityBus_storage5_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage5_2)_: ++1 InvestmentFlowBlock_old(electricityBus_storage5_2) +-1 InvestmentFlowBlock_old_end(electricityBus_storage5_2) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage5_2) += 0 c_u_InvestmentFlowBlock_max(storage5_electricityBus_0_0)_: +1 flow(storage5_electricityBus_0_0) @@ -220,6 +190,36 @@ c_u_InvestmentFlowBlock_max(storage5_electricityBus_2_5)_: -1 InvestmentFlowBlock_total(storage5_electricityBus_2) <= 0 +c_u_InvestmentFlowBlock_max(electricityBus_storage5_0_0)_: ++1 flow(electricityBus_storage5_0_0) +-1 InvestmentFlowBlock_total(electricityBus_storage5_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage5_0_1)_: ++1 flow(electricityBus_storage5_0_1) +-1 InvestmentFlowBlock_total(electricityBus_storage5_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage5_1_2)_: ++1 flow(electricityBus_storage5_1_2) +-1 InvestmentFlowBlock_total(electricityBus_storage5_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage5_1_3)_: ++1 flow(electricityBus_storage5_1_3) +-1 InvestmentFlowBlock_total(electricityBus_storage5_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage5_2_4)_: ++1 flow(electricityBus_storage5_2_4) +-1 InvestmentFlowBlock_total(electricityBus_storage5_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage5_2_5)_: ++1 flow(electricityBus_storage5_2_5) +-1 InvestmentFlowBlock_total(electricityBus_storage5_2) +<= 0 + c_e_GenericStorageBlock_balance(storage5_0_0)_: +1 flow(storage5_electricityBus_0_0) -1 flow(electricityBus_storage5_0_0) @@ -268,18 +268,18 @@ c_e_GenericStorageBlock_balanced_cstr(storage5)_: = 0 c_e_GenericStorageBlock_power_coupled(storage5_0)_: --1 InvestmentFlowBlock_total(electricityBus_storage5_0) +1.1 InvestmentFlowBlock_total(storage5_electricityBus_0) +-1 InvestmentFlowBlock_total(electricityBus_storage5_0) = 0 c_e_GenericStorageBlock_power_coupled(storage5_1)_: --1 InvestmentFlowBlock_total(electricityBus_storage5_1) +1.1 InvestmentFlowBlock_total(storage5_electricityBus_1) +-1 InvestmentFlowBlock_total(electricityBus_storage5_1) = 0 c_e_GenericStorageBlock_power_coupled(storage5_2)_: --1 InvestmentFlowBlock_total(electricityBus_storage5_2) +1.1 InvestmentFlowBlock_total(storage5_electricityBus_2) +-1 InvestmentFlowBlock_total(electricityBus_storage5_2) = 0 bounds @@ -298,11 +298,6 @@ bounds 0 <= flow(electricityBus_storage5_2_4) <= +inf 0 <= flow(storage5_electricityBus_2_5) <= +inf 0 <= flow(electricityBus_storage5_2_5) <= +inf - 0 <= InvestmentFlowBlock_total(electricityBus_storage5_0) <= +inf - 0 <= InvestmentFlowBlock_total(electricityBus_storage5_1) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage5_1) <= +inf - 0 <= InvestmentFlowBlock_total(electricityBus_storage5_2) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage5_2) <= +inf 0 <= InvestmentFlowBlock_total(storage5_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_invest(storage5_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_total(storage5_electricityBus_1) <= +inf @@ -311,20 +306,25 @@ bounds 0 <= InvestmentFlowBlock_total(storage5_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_invest(storage5_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old(storage5_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage5_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage5_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(electricityBus_storage5_2) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage5_0) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage5_1) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage5_1) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage5_2) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage5_2) <= +inf 0 <= InvestmentFlowBlock_old_end(storage5_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_old_end(storage5_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old_end(storage5_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage5_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage5_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage5_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage5_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage5_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage5_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage5_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage5_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage5_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old(electricityBus_storage5_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage5_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage5_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage5_2) <= +inf 0 <= InvestmentFlowBlock_old(storage5_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage5_0) <= +inf 0 <= GenericStorageBlock_storage_content(storage5_1) <= 10000 0 <= GenericStorageBlock_storage_content(storage5_0) <= 10000 0 <= GenericStorageBlock_storage_content(storage5_2) <= 10000 diff --git a/tests/lp_files/storage_invest_6_multi_period.lp b/tests/lp_files/storage_invest_6_multi_period.lp index 8ad4b9f42..4fc195eda 100644 --- a/tests/lp_files/storage_invest_6_multi_period.lp +++ b/tests/lp_files/storage_invest_6_multi_period.lp @@ -2,12 +2,12 @@ min objective: -+121.09030188807486 InvestmentFlowBlock_invest(electricityBus_storage6_0) -+118.71598224321065 InvestmentFlowBlock_invest(electricityBus_storage6_1) -+116.38821788550062 InvestmentFlowBlock_invest(electricityBus_storage6_2) -+177.35448256334197 GenericInvestmentStorageBlock_invest(storage6_0) -+173.87694368955096 GenericInvestmentStorageBlock_invest(storage6_1) -+170.46759185250093 GenericInvestmentStorageBlock_invest(storage6_2) ++17.46051480474446 InvestmentFlowBlock_invest(electricityBus_storage6_0) ++11.524715692583884 InvestmentFlowBlock_invest(electricityBus_storage6_1) ++5.705304798308859 InvestmentFlowBlock_invest(electricityBus_storage6_2) ++25.57348127967623 GenericInvestmentStorageBlock_invest(storage6_0) ++16.879634095198618 GenericInvestmentStorageBlock_invest(storage6_1) ++8.35625450257358 GenericInvestmentStorageBlock_invest(storage6_2) s.t. diff --git a/tests/lp_files/storage_invest_all_nonconvex_multi_period.lp b/tests/lp_files/storage_invest_all_nonconvex_multi_period.lp index 68765fd78..b78eca2f7 100644 --- a/tests/lp_files/storage_invest_all_nonconvex_multi_period.lp +++ b/tests/lp_files/storage_invest_all_nonconvex_multi_period.lp @@ -2,23 +2,23 @@ min objective: -+12.231343625058066 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) -+10 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) -+11.991513357900065 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) -+9.80392156862745 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) -+11.756385645000064 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) -+9.611687812379854 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) -+12.231343625058066 InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_0) ++1.7636883641156018 InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_0) +15 InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_0) -+11.991513357900065 InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_1) ++1.164112696220594 InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_1) +14.705882352941176 InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_1) -+11.756385645000064 InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_2) ++0.5762934139705919 InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_2) +14.41753171856978 InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_2) -+24.462687250116133 GenericInvestmentStorageBlock_invest(storage_all_nonconvex_0) ++1.7636883641156018 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) ++10 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) ++1.164112696220594 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) ++9.80392156862745 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) ++0.5762934139705919 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) ++9.611687812379854 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) ++3.5273767282312036 GenericInvestmentStorageBlock_invest(storage_all_nonconvex_0) +30 GenericInvestmentStorageBlock_invest_status(storage_all_nonconvex_0) -+23.98302671580013 GenericInvestmentStorageBlock_invest(storage_all_nonconvex_1) ++2.328225392441188 GenericInvestmentStorageBlock_invest(storage_all_nonconvex_1) +29.41176470588235 GenericInvestmentStorageBlock_invest_status(storage_all_nonconvex_1) -+23.512771290000128 GenericInvestmentStorageBlock_invest(storage_all_nonconvex_2) ++1.1525868279411837 GenericInvestmentStorageBlock_invest(storage_all_nonconvex_2) +28.83506343713956 GenericInvestmentStorageBlock_invest_status(storage_all_nonconvex_2) s.t. @@ -53,21 +53,6 @@ c_e_BusBlock_balance(bus1_2_5)_: -1 flow(bus1_storage_all_nonconvex_2_5) = 0 -c_u_InvestmentFlowBlock_minimum_rule(bus1_storage_all_nonconvex_0)_: --1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) -+5 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) -<= 0 - -c_u_InvestmentFlowBlock_minimum_rule(bus1_storage_all_nonconvex_1)_: --1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) -+5 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) -<= 0 - -c_u_InvestmentFlowBlock_minimum_rule(bus1_storage_all_nonconvex_2)_: --1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) -+5 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) -<= 0 - c_u_InvestmentFlowBlock_minimum_rule(storage_all_nonconvex_bus1_0)_: -1 InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_0) +8 InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_0) @@ -83,19 +68,19 @@ c_u_InvestmentFlowBlock_minimum_rule(storage_all_nonconvex_bus1_2)_: +8 InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_2) <= 0 -c_u_InvestmentFlowBlock_maximum_rule(bus1_storage_all_nonconvex_0)_: -+1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) --30 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) +c_u_InvestmentFlowBlock_minimum_rule(bus1_storage_all_nonconvex_0)_: +-1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) ++5 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) <= 0 -c_u_InvestmentFlowBlock_maximum_rule(bus1_storage_all_nonconvex_1)_: -+1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) --30 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) +c_u_InvestmentFlowBlock_minimum_rule(bus1_storage_all_nonconvex_1)_: +-1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) ++5 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) <= 0 -c_u_InvestmentFlowBlock_maximum_rule(bus1_storage_all_nonconvex_2)_: -+1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) --30 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) +c_u_InvestmentFlowBlock_minimum_rule(bus1_storage_all_nonconvex_2)_: +-1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) ++5 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) <= 0 c_u_InvestmentFlowBlock_maximum_rule(storage_all_nonconvex_bus1_0)_: @@ -113,24 +98,20 @@ c_u_InvestmentFlowBlock_maximum_rule(storage_all_nonconvex_bus1_2)_: -20 InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_2) <= 0 -c_e_InvestmentFlowBlock_total_rule(bus1_storage_all_nonconvex_0)_: --1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) -+1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) -= 0 +c_u_InvestmentFlowBlock_maximum_rule(bus1_storage_all_nonconvex_0)_: ++1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) +-30 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) +<= 0 -c_e_InvestmentFlowBlock_total_rule(bus1_storage_all_nonconvex_1)_: --1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) --1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) -+1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) -+1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_1) -= 0 +c_u_InvestmentFlowBlock_maximum_rule(bus1_storage_all_nonconvex_1)_: ++1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) +-30 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) +<= 0 -c_e_InvestmentFlowBlock_total_rule(bus1_storage_all_nonconvex_2)_: --1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) --1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) -+1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_2) -+1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_2) -= 0 +c_u_InvestmentFlowBlock_maximum_rule(bus1_storage_all_nonconvex_2)_: ++1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) +-30 InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) +<= 0 c_e_InvestmentFlowBlock_total_rule(storage_all_nonconvex_bus1_0)_: -1 InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_0) @@ -151,16 +132,23 @@ c_e_InvestmentFlowBlock_total_rule(storage_all_nonconvex_bus1_2)_: +1 InvestmentFlowBlock_old(storage_all_nonconvex_bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(bus1_storage_all_nonconvex_0)_: -+1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_0) +c_e_InvestmentFlowBlock_total_rule(bus1_storage_all_nonconvex_0)_: +-1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) ++1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(bus1_storage_all_nonconvex_1)_: -+1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_1) +c_e_InvestmentFlowBlock_total_rule(bus1_storage_all_nonconvex_1)_: +-1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) +-1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) ++1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) ++1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(bus1_storage_all_nonconvex_2)_: -+1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_2) +c_e_InvestmentFlowBlock_total_rule(bus1_storage_all_nonconvex_2)_: +-1 InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) +-1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) ++1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_2) ++1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(storage_all_nonconvex_bus1_0)_: @@ -175,16 +163,16 @@ c_e_InvestmentFlowBlock_old_rule_end(storage_all_nonconvex_bus1_2)_: +1 InvestmentFlowBlock_old_end(storage_all_nonconvex_bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(bus1_storage_all_nonconvex_0)_: -+1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_0) +c_e_InvestmentFlowBlock_old_rule_end(bus1_storage_all_nonconvex_0)_: ++1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(bus1_storage_all_nonconvex_1)_: -+1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_1) +c_e_InvestmentFlowBlock_old_rule_end(bus1_storage_all_nonconvex_1)_: ++1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(bus1_storage_all_nonconvex_2)_: -+1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_2) +c_e_InvestmentFlowBlock_old_rule_end(bus1_storage_all_nonconvex_2)_: ++1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(storage_all_nonconvex_bus1_0)_: @@ -199,22 +187,16 @@ c_e_InvestmentFlowBlock_old_rule_exo(storage_all_nonconvex_bus1_2)_: +1 InvestmentFlowBlock_old_exo(storage_all_nonconvex_bus1_2) = 0 -c_e_InvestmentFlowBlock_old_rule(bus1_storage_all_nonconvex_0)_: --1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_0) --1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_0) -+1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_0) +c_e_InvestmentFlowBlock_old_rule_exo(bus1_storage_all_nonconvex_0)_: ++1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_0) = 0 -c_e_InvestmentFlowBlock_old_rule(bus1_storage_all_nonconvex_1)_: -+1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_1) --1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_1) --1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_1) +c_e_InvestmentFlowBlock_old_rule_exo(bus1_storage_all_nonconvex_1)_: ++1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_1) = 0 -c_e_InvestmentFlowBlock_old_rule(bus1_storage_all_nonconvex_2)_: -+1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_2) --1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_2) --1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_2) +c_e_InvestmentFlowBlock_old_rule_exo(bus1_storage_all_nonconvex_2)_: ++1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_2) = 0 c_e_InvestmentFlowBlock_old_rule(storage_all_nonconvex_bus1_0)_: @@ -235,35 +217,23 @@ c_e_InvestmentFlowBlock_old_rule(storage_all_nonconvex_bus1_2)_: -1 InvestmentFlowBlock_old_exo(storage_all_nonconvex_bus1_2) = 0 -c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_0_0)_: -+1 flow(bus1_storage_all_nonconvex_0_0) --1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) -<= 0 - -c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_0_1)_: -+1 flow(bus1_storage_all_nonconvex_0_1) --1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) -<= 0 - -c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_1_2)_: -+1 flow(bus1_storage_all_nonconvex_1_2) --1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) -<= 0 - -c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_1_3)_: -+1 flow(bus1_storage_all_nonconvex_1_3) --1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) -<= 0 +c_e_InvestmentFlowBlock_old_rule(bus1_storage_all_nonconvex_0)_: +-1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_0) +-1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_0) ++1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_0) += 0 -c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_2_4)_: -+1 flow(bus1_storage_all_nonconvex_2_4) --1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(bus1_storage_all_nonconvex_1)_: ++1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_1) +-1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_1) +-1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_1) += 0 -c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_2_5)_: -+1 flow(bus1_storage_all_nonconvex_2_5) --1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(bus1_storage_all_nonconvex_2)_: ++1 InvestmentFlowBlock_old(bus1_storage_all_nonconvex_2) +-1 InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_2) +-1 InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_2) += 0 c_u_InvestmentFlowBlock_max(storage_all_nonconvex_bus1_0_0)_: +1 flow(storage_all_nonconvex_bus1_0_0) @@ -295,6 +265,36 @@ c_u_InvestmentFlowBlock_max(storage_all_nonconvex_bus1_2_5)_: -1 InvestmentFlowBlock_total(storage_all_nonconvex_bus1_2) <= 0 +c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_0_0)_: ++1 flow(bus1_storage_all_nonconvex_0_0) +-1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) +<= 0 + +c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_0_1)_: ++1 flow(bus1_storage_all_nonconvex_0_1) +-1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) +<= 0 + +c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_1_2)_: ++1 flow(bus1_storage_all_nonconvex_1_2) +-1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) +<= 0 + +c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_1_3)_: ++1 flow(bus1_storage_all_nonconvex_1_3) +-1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) +<= 0 + +c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_2_4)_: ++1 flow(bus1_storage_all_nonconvex_2_4) +-1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_2) +<= 0 + +c_u_InvestmentFlowBlock_max(bus1_storage_all_nonconvex_2_5)_: ++1 flow(bus1_storage_all_nonconvex_2_5) +-1 InvestmentFlowBlock_total(bus1_storage_all_nonconvex_2) +<= 0 + c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_all_nonconvex_0)_: -1 GenericInvestmentStorageBlock_invest(storage_all_nonconvex_0) +1 GenericInvestmentStorageBlock_total(storage_all_nonconvex_0) @@ -456,18 +456,18 @@ c_l_GenericInvestmentStorageBlock_limit_min(storage_all_nonconvex_2)_: >= 0 bounds - 0 <= InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) <= 30 - 0 <= InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) <= 1 - 0 <= InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) <= 30 - 0 <= InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) <= 1 - 0 <= InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) <= 30 - 0 <= InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) <= 1 0 <= InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_0) <= 20 0 <= InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_0) <= 1 0 <= InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_1) <= 20 0 <= InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_1) <= 1 0 <= InvestmentFlowBlock_invest(storage_all_nonconvex_bus1_2) <= 20 0 <= InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_2) <= 1 + 0 <= InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_0) <= 30 + 0 <= InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) <= 1 + 0 <= InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_1) <= 30 + 0 <= InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) <= 1 + 0 <= InvestmentFlowBlock_invest(bus1_storage_all_nonconvex_2) <= 30 + 0 <= InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) <= 1 0 <= GenericInvestmentStorageBlock_invest(storage_all_nonconvex_0) <= 100 0 <= GenericInvestmentStorageBlock_invest_status(storage_all_nonconvex_0) <= 1 0 <= GenericInvestmentStorageBlock_invest(storage_all_nonconvex_1) <= 100 @@ -486,30 +486,30 @@ bounds 0 <= flow(bus1_storage_all_nonconvex_2_4) <= +inf 0 <= flow(storage_all_nonconvex_bus1_2_5) <= +inf 0 <= flow(bus1_storage_all_nonconvex_2_5) <= +inf - 0 <= InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) <= +inf - 0 <= InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) <= +inf - 0 <= InvestmentFlowBlock_old(bus1_storage_all_nonconvex_1) <= +inf - 0 <= InvestmentFlowBlock_total(bus1_storage_all_nonconvex_2) <= +inf - 0 <= InvestmentFlowBlock_old(bus1_storage_all_nonconvex_2) <= +inf 0 <= InvestmentFlowBlock_total(storage_all_nonconvex_bus1_0) <= +inf 0 <= InvestmentFlowBlock_total(storage_all_nonconvex_bus1_1) <= +inf 0 <= InvestmentFlowBlock_old(storage_all_nonconvex_bus1_1) <= +inf 0 <= InvestmentFlowBlock_total(storage_all_nonconvex_bus1_2) <= +inf 0 <= InvestmentFlowBlock_old(storage_all_nonconvex_bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_2) <= +inf + 0 <= InvestmentFlowBlock_total(bus1_storage_all_nonconvex_0) <= +inf + 0 <= InvestmentFlowBlock_total(bus1_storage_all_nonconvex_1) <= +inf + 0 <= InvestmentFlowBlock_old(bus1_storage_all_nonconvex_1) <= +inf + 0 <= InvestmentFlowBlock_total(bus1_storage_all_nonconvex_2) <= +inf + 0 <= InvestmentFlowBlock_old(bus1_storage_all_nonconvex_2) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_all_nonconvex_bus1_0) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_all_nonconvex_bus1_1) <= +inf 0 <= InvestmentFlowBlock_old_end(storage_all_nonconvex_bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(bus1_storage_all_nonconvex_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_all_nonconvex_bus1_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_all_nonconvex_bus1_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(storage_all_nonconvex_bus1_2) <= +inf - 0 <= InvestmentFlowBlock_old(bus1_storage_all_nonconvex_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(bus1_storage_all_nonconvex_2) <= +inf 0 <= InvestmentFlowBlock_old(storage_all_nonconvex_bus1_0) <= +inf + 0 <= InvestmentFlowBlock_old(bus1_storage_all_nonconvex_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_all_nonconvex_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_all_nonconvex_1) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage_all_nonconvex_1) <= +inf @@ -529,12 +529,12 @@ bounds 0 <= GenericInvestmentStorageBlock_storage_content(storage_all_nonconvex_4) <= +inf 0 <= GenericInvestmentStorageBlock_storage_content(storage_all_nonconvex_5) <= +inf binary - InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) - InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) - InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_0) InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_1) InvestmentFlowBlock_invest_status(storage_all_nonconvex_bus1_2) + InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_0) + InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_1) + InvestmentFlowBlock_invest_status(bus1_storage_all_nonconvex_2) GenericInvestmentStorageBlock_invest_status(storage_all_nonconvex_0) GenericInvestmentStorageBlock_invest_status(storage_all_nonconvex_1) GenericInvestmentStorageBlock_invest_status(storage_all_nonconvex_2) diff --git a/tests/lp_files/storage_invest_minimum_multi_period.lp b/tests/lp_files/storage_invest_minimum_multi_period.lp index 76e8aa662..c61a64544 100644 --- a/tests/lp_files/storage_invest_minimum_multi_period.lp +++ b/tests/lp_files/storage_invest_minimum_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+212.02333722461535 GenericInvestmentStorageBlock_invest(storage1_0) -+207.8660168868778 GenericInvestmentStorageBlock_invest(storage1_1) -+203.7902126341939 GenericInvestmentStorageBlock_invest(storage1_2) ++15.2862638908257 GenericInvestmentStorageBlock_invest(storage1_0) ++10.089613468653715 GenericInvestmentStorageBlock_invest(storage1_1) ++4.994858152798875 GenericInvestmentStorageBlock_invest(storage1_2) s.t. diff --git a/tests/lp_files/storage_invest_multi_period.lp b/tests/lp_files/storage_invest_multi_period.lp index 228aadf96..49c4f5e84 100644 --- a/tests/lp_files/storage_invest_multi_period.lp +++ b/tests/lp_files/storage_invest_multi_period.lp @@ -3,9 +3,9 @@ min objective: +250.0 ONE_VAR_CONSTANT -+351.53628135238 GenericInvestmentStorageBlock_invest(storage1_0) -+341.9615033610845 GenericInvestmentStorageBlock_invest(storage1_1) -+332.6786079381219 GenericInvestmentStorageBlock_invest(storage1_2) ++29.99406858132935 GenericInvestmentStorageBlock_invest(storage1_0) ++19.60706904757886 GenericInvestmentStorageBlock_invest(storage1_1) ++9.614085282931445 GenericInvestmentStorageBlock_invest(storage1_2) s.t. diff --git a/tests/lp_files/storage_invest_with_offset_multi_period.lp b/tests/lp_files/storage_invest_with_offset_multi_period.lp index 9fb9d7680..0391a3236 100644 --- a/tests/lp_files/storage_invest_with_offset_multi_period.lp +++ b/tests/lp_files/storage_invest_with_offset_multi_period.lp @@ -14,11 +14,11 @@ objective: +23.52941176470588 flow(storage_non_convex_electricityBus_1_3) +23.06805074971165 flow(storage_non_convex_electricityBus_2_4) +23.06805074971165 flow(storage_non_convex_electricityBus_2_5) -+177.35448256334197 GenericInvestmentStorageBlock_invest(storage_non_convex_0) ++25.57348127967623 GenericInvestmentStorageBlock_invest(storage_non_convex_0) +5 GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) -+173.87694368955096 GenericInvestmentStorageBlock_invest(storage_non_convex_1) ++16.879634095198618 GenericInvestmentStorageBlock_invest(storage_non_convex_1) +4.901960784313725 GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) -+170.46759185250093 GenericInvestmentStorageBlock_invest(storage_non_convex_2) ++8.35625450257358 GenericInvestmentStorageBlock_invest(storage_non_convex_2) +4.805843906189927 GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) s.t. @@ -53,25 +53,6 @@ c_e_BusBlock_balance(electricityBus_2_5)_: +1 flow(storage_non_convex_electricityBus_2_5) = 0 -c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_0)_: -+1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) --1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_1)_: --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) -+1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) --1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_2)_: --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) -+1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) --1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) -= 0 - c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_0)_: +1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) -1 InvestmentFlowBlock_invest(electricityBus_storage_non_convex_0) @@ -91,16 +72,23 @@ c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_2)_: +1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_0)_: -+1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_1)_: -+1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_1)_: +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_2)_: -+1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_2)_: +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_0)_: @@ -115,16 +103,16 @@ c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_2)_: +1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_0)_: -+1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_1)_: -+1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_2)_: -+1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_0)_: @@ -139,22 +127,16 @@ c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_2)_: +1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_0)_: --1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) --1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_1)_: -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) --1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) --1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_2)_: -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) --1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) --1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_0)_: @@ -175,35 +157,23 @@ c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_2)_: -1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) = 0 -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_0)_: -+1 flow(storage_non_convex_electricityBus_0_0) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_1)_: -+1 flow(storage_non_convex_electricityBus_0_1) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_2)_: -+1 flow(storage_non_convex_electricityBus_1_2) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_3)_: -+1 flow(storage_non_convex_electricityBus_1_3) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_0)_: +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) += 0 -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_4)_: -+1 flow(storage_non_convex_electricityBus_2_4) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) += 0 -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_5)_: -+1 flow(storage_non_convex_electricityBus_2_5) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) += 0 c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_0_0)_: +1 flow(electricityBus_storage_non_convex_0_0) @@ -235,6 +205,36 @@ c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_2_5)_: -1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) <= 0 +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_0)_: ++1 flow(storage_non_convex_electricityBus_0_0) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_1)_: ++1 flow(storage_non_convex_electricityBus_0_1) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_2)_: ++1 flow(storage_non_convex_electricityBus_1_2) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_3)_: ++1 flow(storage_non_convex_electricityBus_1_3) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_4)_: ++1 flow(storage_non_convex_electricityBus_2_4) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_5)_: ++1 flow(storage_non_convex_electricityBus_2_5) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +<= 0 + c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_non_convex_0)_: -1 GenericInvestmentStorageBlock_invest(storage_non_convex_0) +1 GenericInvestmentStorageBlock_total(storage_non_convex_0) @@ -474,14 +474,6 @@ bounds 0 <= GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) <= 1 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_2) <= 1454 0 <= GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) <= 1 - 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) <= +inf 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_0) <= +inf 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) <= +inf @@ -490,20 +482,28 @@ bounds 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) <= +inf 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_2) <= +inf 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_0) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_1) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) <= +inf - 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_1) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage_non_convex_1) <= +inf diff --git a/tests/lp_files/storage_invest_without_offset_multi_period.lp b/tests/lp_files/storage_invest_without_offset_multi_period.lp index 3e98a271f..f4a182548 100644 --- a/tests/lp_files/storage_invest_without_offset_multi_period.lp +++ b/tests/lp_files/storage_invest_without_offset_multi_period.lp @@ -14,9 +14,9 @@ objective: +23.52941176470588 flow(storage_non_convex_electricityBus_1_3) +23.06805074971165 flow(storage_non_convex_electricityBus_2_4) +23.06805074971165 flow(storage_non_convex_electricityBus_2_5) -+172.46194511331876 GenericInvestmentStorageBlock_invest(storage_non_convex_0) -+169.08033834639093 GenericInvestmentStorageBlock_invest(storage_non_convex_1) -+165.7650375945009 GenericInvestmentStorageBlock_invest(storage_non_convex_2) ++24.868005934029988 GenericInvestmentStorageBlock_invest(storage_non_convex_0) ++16.413989016710378 GenericInvestmentStorageBlock_invest(storage_non_convex_1) ++8.125737136985347 GenericInvestmentStorageBlock_invest(storage_non_convex_2) s.t. @@ -50,25 +50,6 @@ c_e_BusBlock_balance(electricityBus_2_5)_: +1 flow(storage_non_convex_electricityBus_2_5) = 0 -c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_0)_: -+1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) --1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_1)_: --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) -+1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) --1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_2)_: --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) -+1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) --1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) -= 0 - c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_0)_: +1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) -1 InvestmentFlowBlock_invest(electricityBus_storage_non_convex_0) @@ -88,16 +69,23 @@ c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_2)_: +1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_0)_: -+1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_1)_: -+1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_1)_: +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_2)_: -+1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_2)_: +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_0)_: @@ -112,16 +100,16 @@ c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_2)_: +1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_0)_: -+1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_1)_: -+1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_2)_: -+1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_0)_: @@ -136,22 +124,16 @@ c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_2)_: +1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_0)_: --1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) --1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_1)_: -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) --1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) --1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_2)_: -+1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) --1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) --1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_0)_: @@ -172,35 +154,23 @@ c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_2)_: -1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) = 0 -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_0)_: -+1 flow(storage_non_convex_electricityBus_0_0) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_1)_: -+1 flow(storage_non_convex_electricityBus_0_1) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_2)_: -+1 flow(storage_non_convex_electricityBus_1_2) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_3)_: -+1 flow(storage_non_convex_electricityBus_1_3) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_0)_: +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) += 0 -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_4)_: -+1 flow(storage_non_convex_electricityBus_2_4) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) += 0 -c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_5)_: -+1 flow(storage_non_convex_electricityBus_2_5) --1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) += 0 c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_0_0)_: +1 flow(electricityBus_storage_non_convex_0_0) @@ -232,6 +202,36 @@ c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_2_5)_: -1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) <= 0 +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_0)_: ++1 flow(storage_non_convex_electricityBus_0_0) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_1)_: ++1 flow(storage_non_convex_electricityBus_0_1) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_2)_: ++1 flow(storage_non_convex_electricityBus_1_2) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_3)_: ++1 flow(storage_non_convex_electricityBus_1_3) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_4)_: ++1 flow(storage_non_convex_electricityBus_2_4) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_5)_: ++1 flow(storage_non_convex_electricityBus_2_5) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +<= 0 + c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_non_convex_0)_: -1 GenericInvestmentStorageBlock_invest(storage_non_convex_0) +1 GenericInvestmentStorageBlock_total(storage_non_convex_0) @@ -468,14 +468,6 @@ bounds 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_0) <= 244 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_1) <= 244 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_2) <= 244 - 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) <= +inf 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_0) <= +inf 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) <= +inf @@ -484,20 +476,28 @@ bounds 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) <= +inf 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_2) <= +inf 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_0) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_1) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) <= +inf - 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_1) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage_non_convex_1) <= +inf From 787a4a912e3b50a352415febaba28ff355a0c565 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 16:47:33 +0200 Subject: [PATCH 025/180] Extend changelog for v0.5.2 --- docs/whatsnew/v0-5-2.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index d9d20b7be..a97735187 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -13,6 +13,11 @@ Documentation Bug fixes ######### +* Fix handling of investment annuities and fixed costs for multi-period models: + Limit to costs that occur within the optimization horizon to prevent a + bias towards investments happening earlier in the optimization horizon. +* Fix bugs in multi-period documentation. + Testing ####### @@ -21,3 +26,8 @@ Other changes Contributors ############ + +* Patrik Schönfeldt +* Johannes Kochems +* Julian Endres +* Hendrik Huysgens From f1845affa5b19fdaa5ba9fc35b8ee4fe706f3f43 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 17:42:30 +0200 Subject: [PATCH 026/180] Adjust docs for invest flow --- .../solph/flows/_investment_flow_block.py | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index c6c05e224..695f979ac 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -779,8 +779,8 @@ def _objective_expression(self): .. math:: & - P_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) \cdot l - \cdot DF^{-p}\\ + P_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) + \cdot \frac {1}{ANF(d, dr)} \cdot DF^{-p}\\ &\\ & \forall p \in \textrm{PERIODS} @@ -789,8 +789,10 @@ def _objective_expression(self): .. math:: & - (P_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) \cdot l - + c_{invest,fix}(p) \cdot b_{invest}(p)) \cdot DF^{-p} \\ + (P_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) + \cdot \frac {1}{ANF(d, dr)}\\ + & + + c_{invest,fix}(p) \cdot b_{invest}(p)) \cdot DF^{-p}\\ &\\ & \forall p \in \textrm{PERIODS} @@ -799,7 +801,7 @@ def _objective_expression(self): .. math:: & - (\sum_{pp=year(p)}^{year(p)+l} + (\sum_{pp=year(p)}^{limit_{end}} P_{invest}(p) \cdot c_{fixed}(pp) \cdot DF^{-pp}) \cdot DF^{-p}\\ &\\ @@ -809,28 +811,45 @@ def _objective_expression(self): * :attr:`fixed_costs` not None for existing capacity .. math:: - \sum_{pp=0}^{l-a} P_{exist} \cdot c_{fixed}(pp) + \sum_{pp=0}^{limit_{exo}} P_{exist} \cdot c_{fixed}(pp) \cdot DF^{-pp} whereby: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for - investment expenses :math:`c_{invest,var}(p)` lifetime :math:`l` - and interest rate :math:`ir` - * :math:`DF=(1+dr)` is the discount factor with discount rate - :math:`dr` - - The annuity hereby is: + investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` + and interest rate :math:`ir`. + * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` + and discount rate :math:`dr`. + * :math:`d=min\{year_{max} - year(p), l\}` defines the + number of years within the optimization horizon that investment + annuities are accounted for. + * :math:`year(p)` denotes the start year of period :math:`p`. + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. + * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an + upper bound to ensure fixed costs for endogenous investments + to occur within the optimization horizon. + * :math:`limit_{exo}=min\{year_{max}, l - a\}` is used as an + upper bound to ensure fixed costs for existing capacities to occur + within the optimization horizon. :math:`a` is the initial age + of an asset. + * :math:`DF=(1+dr)` is the discount factor. + + The annuity / annuity factor hereby is: .. math:: - + & A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot - \frac {(1+i)^l \cdot i} {(1+i)^l - 1} \cdot + \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + &\\ + & + ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} - It is retrieved, using oemof.tools.economics annuity function. The - interest rate is defined as a weighted average costs of capital (wacc) - and assumed constant over time. + They are retrieved, using oemof.tools.economics annuity function. The + interest rate :math:`i` for the annuity is defined as weighted + average costs of capital (wacc) and assumed constant over time. """ if not hasattr(self, "INVESTFLOWS"): return 0 From caf6cd6096946636631689cfb0d9989669f43d68 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 17:59:11 +0200 Subject: [PATCH 027/180] Adjust storage docs and add minor fixes --- .../solph/components/_generic_storage.py | 63 +++++++++++++------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 04e86198c..5a4c41fb4 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -363,7 +363,7 @@ class GenericStorageBlock(ScalarBlock): Set storage_content of last time step to one at t=0 if balanced == True .. math:: - E(t_{last}) = &E(-1) + E(t_{last}) = E(-1) Storage balance :attr:`om.Storage.balance[n, t]` .. math:: E(t) = &E(t-1) \cdot @@ -376,8 +376,8 @@ class GenericStorageBlock(ScalarBlock): Connect the invest variables of the input and the output flow. .. math:: InvestmentFlowBlock.invest(source(n), n, p) + existing = \\ - (InvestmentFlowBlock.invest(n, target(n), p) + existing) * \\ - invest\_relation\_input\_output(n) \\ + (InvestmentFlowBlock.invest(n, target(n), p) + existing) \\ + * invest\_relation\_input\_output(n) \\ \forall n \in \textrm{INVEST\_REL\_IN\_OUT} \\ \forall p \in \textrm{PERIODS} @@ -430,7 +430,7 @@ class GenericStorageBlock(ScalarBlock): * :attr: `storage_costs` not 0 - ..math:: + .. math:: \sum_{t \in \textrm{TIMESTEPS}} c_{storage}(t) \cdot E(t) @@ -884,14 +884,17 @@ class GenericInvestmentStorageBlock(ScalarBlock): E_{invest}(0) \cdot c_{invest,var}(0) + c_{invest,fix}(0) \cdot b_{invest}(0)\\ + Whereby 0 denotes the 0th (investment) period since + in a standard model, there is only this one period. + *Multi-period model* * :attr:`nonconvex = False` .. math:: & - E_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) \cdot l - \cdot DF^{-p}\\ + E_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) + \cdot \frac {1}{ANF(d, dr)} \cdot DF^{-p}\\ & \forall p \in \textrm{PERIODS} @@ -899,8 +902,10 @@ class GenericInvestmentStorageBlock(ScalarBlock): .. math:: & - E_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) \cdot l - \cdot DF^{-p} + c_{invest,fix}(p) \cdot b_{invest}(p)\\ + (E_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) + \cdot \frac {1}{ANF(d, dr)}\\ + & + + c_{invest,fix}(p) \cdot b_{invest}(p)) \cdot DF^{-p} \\ & \forall p \in \textrm{PERIODS} @@ -908,7 +913,7 @@ class GenericInvestmentStorageBlock(ScalarBlock): .. math:: & - \sum_{pp=year(p)}^{year(p)+l} + \sum_{pp=year(p)}^{limit_{end}} E_{invest}(p) \cdot c_{fixed}(pp) \cdot DF^{-pp}) \cdot DF^{-p}\\ & @@ -917,27 +922,45 @@ class GenericInvestmentStorageBlock(ScalarBlock): * :attr:`fixed_costs` not None for existing capacity .. math:: - \sum_{pp=0}^{l-a} E_{exist} \cdot c_{fixed}(pp) + \sum_{pp=0}^{limit_{exo}} E_{exist} \cdot c_{fixed}(pp) \cdot DF^{-pp} whereby: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for - investment expenses :math:`c_{invest,var}(p)` lifetime :math:`l` and - interest rate :math:`ir` - * :math:`DF=(1+dr)` is the discount factor with discount rate math:`dr` - - The annuity hereby is: + investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` + and interest rate :math:`ir`. + * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` + and discount rate :math:`dr`. + * :math:`d=min\{year_{max} - year(p), l\}` defines the + number of years within the optimization horizon that investment + annuities are accounted for. + * :math:`year(p)` denotes the start year of period :math:`p`. + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. + * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an + upper bound to ensure fixed costs for endogenous investments + to occur within the optimization horizon. + * :math:`limit_{exo}=min\{year_{max}, l - a\}` is used as an + upper bound to ensure fixed costs for existing capacities to occur + within the optimization horizon. :math:`a` is the initial age + of an asset. + * :math:`DF=(1+dr)` is the discount factor. + + The annuity / annuity factor hereby is: .. math:: - + & A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot - \frac {(1+i)^l \cdot i} {(1+i)^l - 1} \cdot + \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + &\\ + & + ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} - It is retrieved, using oemof.tools.economics annuity function. The - interest rate is defined as a weighted average costs of capital (wacc) and - assumed constant over time. + They are retrieved, using oemof.tools.economics annuity function. The + interest rate :math:`i` for the annuity is defined as weighted + average costs of capital (wacc) and assumed constant over time. The overall summed cost expressions for all *InvestmentFlowBlock* objects can be accessed by From f6f9a4dc5730db1cc0dd0378fb111a3de510971d Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 18:28:58 +0200 Subject: [PATCH 028/180] Adjust docs for sink dsm --- .../components/experimental/_sink_dsm.py | 116 ++++++++++++++---- 1 file changed, 94 insertions(+), 22 deletions(-) diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index bb53bbd74..5cbddd865 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -780,8 +780,8 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): .. math:: & - P_{invest}(p) \cdot A(c_{invest}(p), l, ir) \cdot l - \cdot DF^{-p} \\ + P_{invest}(p) \cdot A(c_{invest}(p), l, ir) + \cdot \frac {1}{ANF(d, dr)} \cdot DF^{-p} \\ &\\ & \forall p \in \mathbb{P} @@ -790,7 +790,7 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): .. math:: & - (\sum_{pp=year(p)}^{year(p)+l} + (\sum_{pp=year(p)}^{limit_{end}} P_{invest}(p) \cdot c_{fixed}(pp) \cdot DF^{-pp}) \cdot DF^{-p} \\ &\\ @@ -812,10 +812,34 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): whereby: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for - investment expenses :math:`c_{invest}(p)` lifetime :math:`l` - and interest rate :math:`ir` - * :math:`DF=(1+dr)` is the discount factor with discount rate - :math:`dr` + investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` + and interest rate :math:`ir`. + * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` + and discount rate :math:`dr`. + * :math:`d=min\{year_{max} - year(p), l\}` defines the + number of years within the optimization horizon that investment + annuities are accounted for. + * :math:`year(p)` denotes the start year of period :math:`p`. + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. + * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an + upper bound to ensure fixed costs for endogenous investments + to occur within the optimization horizon. + * :math:`DF=(1+dr)` is the discount factor. + + The annuity / annuity factor hereby is: + + .. math:: + & + A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot + \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + &\\ + & + ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} + + They are retrieved, using oemof.tools.economics annuity function. The + interest rate :math:`i` for the annuity is defined as weighted + average costs of capital (wacc) and assumed constant over time. See remarks in :class:`oemof.solph.components.experimental._sink_dsm.SinkDSMOemofBlock`. @@ -2181,8 +2205,8 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): .. math:: & - P_{invest}(p) \cdot A(c_{invest}(p), l, ir) \cdot l - \cdot DF^{-p} \\ + P_{invest}(p) \cdot A(c_{invest}(p), l, ir) + \frac {1}{ANF(d, dr)} \cdot DF^{-p} \\ &\\ & \quad \quad \quad \quad \forall p \in \mathbb{P} @@ -2190,7 +2214,7 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): .. math:: & - (\sum_{pp=year(p)}^{year(p)+l} + (\sum_{pp=year(p)}^{limit_{end}} P_{invest}(p) \cdot c_{fixed}(pp) \cdot DF^{-pp}) \cdot DF^{-p} \\ &\\ @@ -2210,11 +2234,35 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): whereby: - * :math:`A(c_{invest,var}(p), l, ir)` is the annuity for - investment expenses :math:`c_{invest}(p)` lifetime :math:`l` - and interest rate :math:`ir` - * :math:`DF=(1+dr)` is the discount factor with discount rate - :math:`dr` + * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for + investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` + and interest rate :math:`ir`. + * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` + and discount rate :math:`dr`. + * :math:`d=min\{year_{max} - year(p), l\}` defines the + number of years within the optimization horizon that investment + annuities are accounted for. + * :math:`year(p)` denotes the start year of period :math:`p`. + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. + * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an + upper bound to ensure fixed costs for endogenous investments + to occur within the optimization horizon. + * :math:`DF=(1+dr)` is the discount factor. + + The annuity / annuity factor hereby is: + + .. math:: + & + A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot + \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + &\\ + & + ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} + + They are retrieved, using oemof.tools.economics annuity function. The + interest rate :math:`i` for the annuity is defined as weighted + average costs of capital (wacc) and assumed constant over time. See remarks in :class:`oemof.solph.components.experimental._sink_dsm.SinkDSMOemofBlock`. @@ -4325,8 +4373,8 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): .. math:: & - P_{invest}(p) \cdot A(c_{invest}(p), l, ir) \cdot l - \cdot DF^{-p} \\ + P_{invest}(p) \cdot A(c_{invest}(p), l, ir) + \cdot \frac {1}{ANF(d, dr)} \cdot DF^{-p} \\ &\\ & \forall p \in \mathbb{P} @@ -4335,7 +4383,7 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): .. math:: & - (\sum_{pp=year(p)}^{year(p)+l} + (\sum_{pp=year(p)}^{limit_{end}} P_{invest}(p) \cdot c_{fixed}(pp) \cdot DF^{-pp}) \cdot DF^{-p} \\ &\\ @@ -4358,10 +4406,34 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): whereby: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for - investment expenses :math:`c_{invest}(p)` lifetime :math:`l` - and interest rate :math:`ir` - * :math:`DF=(1+dr)` is the discount factor with discount rate - :math:`dr` + investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` + and interest rate :math:`ir`. + * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` + and discount rate :math:`dr`. + * :math:`d=min\{year_{max} - year(p), l\}` defines the + number of years within the optimization horizon that investment + annuities are accounted for. + * :math:`year(p)` denotes the start year of period :math:`p`. + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. + * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an + upper bound to ensure fixed costs for endogenous investments + to occur within the optimization horizon. + * :math:`DF=(1+dr)` is the discount factor. + + The annuity / annuity factor hereby is: + + .. math:: + & + A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot + \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + &\\ + & + ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} + + They are retrieved, using oemof.tools.economics annuity function. The + interest rate :math:`i` for the annuity is defined as weighted + average costs of capital (wacc) and assumed constant over time. See remarks in :class:`oemof.solph.components.experimental._sink_dsm.SinkDSMOemofBlock`. From b4010c8514a09bb8d3ba3f3f7e151802b37105d2 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 18:29:07 +0200 Subject: [PATCH 029/180] Alter identation --- .../solph/components/_generic_storage.py | 40 ++++++++-------- .../solph/flows/_investment_flow_block.py | 46 +++++++++---------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 5a4c41fb4..acca08e48 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -926,27 +926,27 @@ class GenericInvestmentStorageBlock(ScalarBlock): \cdot DF^{-pp} - whereby: + whereby: - * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for - investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` - and interest rate :math:`ir`. - * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` - and discount rate :math:`dr`. - * :math:`d=min\{year_{max} - year(p), l\}` defines the - number of years within the optimization horizon that investment - annuities are accounted for. - * :math:`year(p)` denotes the start year of period :math:`p`. - * :math:`year_{max}` denotes the last year of the optimization - horizon, i.e. at the end of the last period. - * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an - upper bound to ensure fixed costs for endogenous investments - to occur within the optimization horizon. - * :math:`limit_{exo}=min\{year_{max}, l - a\}` is used as an - upper bound to ensure fixed costs for existing capacities to occur - within the optimization horizon. :math:`a` is the initial age - of an asset. - * :math:`DF=(1+dr)` is the discount factor. + * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for + investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` + and interest rate :math:`ir`. + * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` + and discount rate :math:`dr`. + * :math:`d=min\{year_{max} - year(p), l\}` defines the + number of years within the optimization horizon that investment + annuities are accounted for. + * :math:`year(p)` denotes the start year of period :math:`p`. + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. + * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an + upper bound to ensure fixed costs for endogenous investments + to occur within the optimization horizon. + * :math:`limit_{exo}=min\{year_{max}, l - a\}` is used as an + upper bound to ensure fixed costs for existing capacities to occur + within the optimization horizon. :math:`a` is the initial age + of an asset. + * :math:`DF=(1+dr)` is the discount factor. The annuity / annuity factor hereby is: diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 695f979ac..b06ab868e 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -815,27 +815,27 @@ def _objective_expression(self): \cdot DF^{-pp} - whereby: - - * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for - investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` - and interest rate :math:`ir`. - * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` - and discount rate :math:`dr`. - * :math:`d=min\{year_{max} - year(p), l\}` defines the - number of years within the optimization horizon that investment - annuities are accounted for. - * :math:`year(p)` denotes the start year of period :math:`p`. - * :math:`year_{max}` denotes the last year of the optimization - horizon, i.e. at the end of the last period. - * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an - upper bound to ensure fixed costs for endogenous investments - to occur within the optimization horizon. - * :math:`limit_{exo}=min\{year_{max}, l - a\}` is used as an - upper bound to ensure fixed costs for existing capacities to occur - within the optimization horizon. :math:`a` is the initial age - of an asset. - * :math:`DF=(1+dr)` is the discount factor. + whereby: + + * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for + investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` + and interest rate :math:`ir`. + * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` + and discount rate :math:`dr`. + * :math:`d=min\{year_{max} - year(p), l\}` defines the + number of years within the optimization horizon that investment + annuities are accounted for. + * :math:`year(p)` denotes the start year of period :math:`p`. + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. + * :math:`limit_{end}=min\{year_{max}, year(p) + l\}` is used as an + upper bound to ensure fixed costs for endogenous investments + to occur within the optimization horizon. + * :math:`limit_{exo}=min\{year_{max}, l - a\}` is used as an + upper bound to ensure fixed costs for existing capacities to occur + within the optimization horizon. :math:`a` is the initial age + of an asset. + * :math:`DF=(1+dr)` is the discount factor. The annuity / annuity factor hereby is: @@ -847,8 +847,8 @@ def _objective_expression(self): & ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} - They are retrieved, using oemof.tools.economics annuity function. The - interest rate :math:`i` for the annuity is defined as weighted + They are retrieved, using oemof.tools.economics annuity function. + The interest rate :math:`i` for the annuity is defined as weighted average costs of capital (wacc) and assumed constant over time. """ if not hasattr(self, "INVESTFLOWS"): From fe2a8c4708a3b9c08854ee5026ef48722fffcd01 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 6 Oct 2023 19:05:26 +0200 Subject: [PATCH 030/180] Fix erroneous return values in docs --- src/oemof/solph/_energy_system.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 5b177b433..29177edfa 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -178,11 +178,9 @@ def __init__( def _extract_periods_years(self): """Map years in optimization to respective period based on time indices - Returns - ------- - periods_years: dict - year of the start of each period, - relative to the start of the optimization run and starting with 0 + Attribute `periods_years` of type list is set. It contains + the year of the start of each period, relative to the + start of the optimization run and starting with 0. """ periods_years = [0] if self.periods is not None: @@ -195,14 +193,11 @@ def _extract_periods_years(self): def _extract_periods_matrix(self): """Determines a matrix describing the temporal distance to each period. + + Attribute `periods_matrix` of type list np.array is set. Rows represent investment/commissioning periods, columns represent decommissioning periods. The values describe the temporal distance between each investment period to each decommissioning period. - - Returns - ------- - period_distance_matrix: np.array - """ periods_matrix = [] if self.periods is not None: From 559c6811d33c5f34d0363071539742b37686153e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 10:38:26 +0200 Subject: [PATCH 031/180] Fix "Flow" does not have "_in_edges" In old versions of oemof.network, Edge was subclass to Node. Thus, the Flow had the attribute "_in_edges" though there was no Edge connected to an Edge. Now, the Edge (sand thus Flow) is cleaned up in oemof.network. As attributes starting with "_" are ignored anyway, this commit does not even change any behaviour. --- src/oemof/solph/processing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oemof/solph/processing.py b/src/oemof/solph/processing.py index f0da8ffc8..2e15ba6b8 100644 --- a/src/oemof/solph/processing.py +++ b/src/oemof/solph/processing.py @@ -528,7 +528,7 @@ def detect_scalars_and_sequences(com): attrs = [ i for i in dir(com) - if not (callable(getattr(com, i)) or i.startswith(exclusions)) + if not (i.startswith(exclusions) or callable(getattr(com, i))) ] for a in attrs: From 9839c377b60819823de471bc7f025bca919626e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 10:52:49 +0200 Subject: [PATCH 032/180] Document changes --- docs/whatsnew/v0-5-2.rst | 4 ++++ src/oemof/solph/processing.py | 1 + 2 files changed, 5 insertions(+) diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index d9d20b7be..76968d64a 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -19,5 +19,9 @@ Testing Other changes ############# +* Improved compatibility with upcoming oemof.network + Contributors ############ + +* Patrik Schönfeldt diff --git a/src/oemof/solph/processing.py b/src/oemof/solph/processing.py index 2e15ba6b8..c641fd436 100644 --- a/src/oemof/solph/processing.py +++ b/src/oemof/solph/processing.py @@ -10,6 +10,7 @@ SPDX-FileCopyrightText: Stephan Günther SPDX-FileCopyrightText: henhuy SPDX-FileCopyrightText: Johannes Kochems +SPDX-FileCopyrightText: Patrik Schönfeldt SPDX-License-Identifier: MIT From c4f93658ae76f1bd50aa3c9633e4778606dc7b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 13:16:51 +0200 Subject: [PATCH 033/180] Delete useless test The test seems to be designed to test if warnings can be turned off. However, the operation never created one. --- tests/test_warnings.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/test_warnings.py b/tests/test_warnings.py index cf465ac53..616277a0c 100644 --- a/tests/test_warnings.py +++ b/tests/test_warnings.py @@ -50,15 +50,6 @@ def test_that_the_sink_errors_actually_get_raised(warning_fixture): assert msg in str(w[-1].message) -def test_filtered_warning(warning_fixture): - """Sink doesn't warn about potentially erroneous usage.""" - warnings.filterwarnings("ignore", category=SuspiciousUsageWarning) - look_out = network.Bus() - with warnings.catch_warnings(record=True) as w: - network.Sink(outputs={look_out: "A typo!"}) - assert len(w) == 0 - - def test_that_the_source_warnings_actually_get_raised(warning_fixture): """Source doesn't warn about potentially erroneous usage.""" look_out = network.Bus() From 860b74237bc955d39ed8389bd8361a41bdeb6493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 13:18:17 +0200 Subject: [PATCH 034/180] Disuse network.Bus in warnings test --- tests/test_warnings.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/test_warnings.py b/tests/test_warnings.py index 616277a0c..c3fac5e37 100644 --- a/tests/test_warnings.py +++ b/tests/test_warnings.py @@ -13,7 +13,6 @@ import pandas as pd import pytest -from oemof.network import network from oemof.tools.debugging import SuspiciousUsageWarning from oemof import solph @@ -31,7 +30,7 @@ def warning_fixture(): def test_that_the_sink_errors_actually_get_raised(warning_fixture): """Sink doesn't warn about potentially erroneous usage.""" - look_out = network.Bus() + look_out = solph.Bus() with pytest.raises( TypeError, match="got an unexpected keyword argument 'outputs'" ): @@ -52,7 +51,7 @@ def test_that_the_sink_errors_actually_get_raised(warning_fixture): def test_that_the_source_warnings_actually_get_raised(warning_fixture): """Source doesn't warn about potentially erroneous usage.""" - look_out = network.Bus() + look_out = solph.Bus() with pytest.raises( TypeError, match="got an unexpected keyword argument 'inputs'" ): @@ -75,7 +74,7 @@ def test_that_the_source_warnings_actually_get_raised(warning_fixture): def test_that_the_converter_warnings_actually_get_raised(warning_fixture): """Converter doesn't warn about potentially erroneous usage.""" - look_out = network.Bus() + look_out = solph.Bus() msg = ( "Attribute is missing in Node of ." @@ -100,7 +99,7 @@ def test_that_the_converter_warnings_actually_get_raised(warning_fixture): def test_storage_without_outputs(warning_fixture): """GenericStorage doesn't warn correctly about missing outputs.""" - look_out = network.Bus() + look_out = solph.Bus() msg = ( "Attribute is missing in Node " " of ." @@ -115,7 +114,7 @@ def test_storage_without_outputs(warning_fixture): def test_storage_without_inputs(warning_fixture): """GenericStorage doesn't warn correctly about missing inputs.""" - look_out = network.Bus() + look_out = solph.Bus() msg = ( "Attribute is missing in Node " " of ." From bda5b402cd6143c06246b04dfa6d9e8cda3b6141 Mon Sep 17 00:00:00 2001 From: Raul Ciria Aylagas <53448419+Raul-Ciria-Aylagas@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:33:48 +0200 Subject: [PATCH 035/180] BUGFIX: GenericStorage investment initialization The __init__ method was malfunctioning with the preferred way to declare investments in the attr nominal_storage_capacity. Probably due to code legacy from older versions. --- src/oemof/solph/components/_generic_storage.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index a10e02ca3..c24ddd2f8 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -217,7 +217,7 @@ def __init__( if isinstance(nominal_storage_capacity, numbers.Real): self.nominal_storage_capacity = nominal_storage_capacity elif isinstance(nominal_storage_capacity, Investment): - self.investment = investment + self.investment = nominal_storage_capacity self._invest_group = True self.initial_storage_level = initial_storage_level @@ -235,11 +235,9 @@ def __init__( self.min_storage_level = solph_sequence(min_storage_level) self.fixed_costs = solph_sequence(fixed_costs) self.storage_costs = solph_sequence(storage_costs) - self.investment = investment self.invest_relation_input_output = invest_relation_input_output self.invest_relation_input_capacity = invest_relation_input_capacity self.invest_relation_output_capacity = invest_relation_output_capacity - self._invest_group = isinstance(self.investment, Investment) self.lifetime_inflow = lifetime_inflow self.lifetime_outflow = lifetime_outflow From 55f3fdc91a7a8704e0d2d8c3c9ba392c6f9a420d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 17:01:25 +0200 Subject: [PATCH 036/180] Disuse subclasses of oemof.network.Node --- src/oemof/solph/buses/_bus.py | 4 ++-- src/oemof/solph/components/_converter.py | 4 ++-- src/oemof/solph/components/_generic_chp.py | 4 ++-- src/oemof/solph/components/_generic_storage.py | 4 ++-- src/oemof/solph/components/_link.py | 4 ++-- src/oemof/solph/components/_offset_converter.py | 4 ++-- src/oemof/solph/components/_sink.py | 4 ++-- src/oemof/solph/components/_source.py | 4 ++-- src/oemof/solph/components/experimental/_generic_caes.py | 4 ++-- .../components/experimental/_piecewise_linear_converter.py | 4 ++-- src/oemof/solph/flows/_flow.py | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/oemof/solph/buses/_bus.py b/src/oemof/solph/buses/_bus.py index 704ddd7a9..20f97ecaa 100644 --- a/src/oemof/solph/buses/_bus.py +++ b/src/oemof/solph/buses/_bus.py @@ -15,13 +15,13 @@ """ -from oemof.network import network as on +from oemof.network import Node from pyomo.core import BuildAction from pyomo.core import Constraint from pyomo.core.base.block import ScalarBlock -class Bus(on.Bus): +class Bus(Node): """A balance object. Every component has to be connected to buses. The sum of all inputs of a Bus object must equal the sum of all outputs diff --git a/src/oemof/solph/components/_converter.py b/src/oemof/solph/components/_converter.py index 90782646b..a2e9a559b 100644 --- a/src/oemof/solph/components/_converter.py +++ b/src/oemof/solph/components/_converter.py @@ -23,7 +23,7 @@ from warnings import warn -from oemof.network import network as on +from oemof.network import Node from pyomo.core import BuildAction from pyomo.core import Constraint from pyomo.core.base.block import ScalarBlock @@ -32,7 +32,7 @@ from oemof.solph._plumbing import sequence -class Converter(on.Transformer): +class Converter(Node): """A linear ConverterBlock object with n inputs and n outputs. Node object that relates any number of inflow and outflows with diff --git a/src/oemof/solph/components/_generic_chp.py b/src/oemof/solph/components/_generic_chp.py index d817f00f5..d7853e2fe 100644 --- a/src/oemof/solph/components/_generic_chp.py +++ b/src/oemof/solph/components/_generic_chp.py @@ -19,7 +19,7 @@ """ import numpy as np -from oemof.network import network +from oemof.network import Node from pyomo.core.base.block import ScalarBlock from pyomo.environ import Binary from pyomo.environ import Constraint @@ -30,7 +30,7 @@ from oemof.solph._plumbing import sequence -class GenericCHP(network.Transformer): +class GenericCHP(Node): r""" Component `GenericCHP` to model combined heat and power plants. diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index a10e02ca3..5175985ad 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -23,7 +23,7 @@ from warnings import warn import numpy as np -from oemof.network import network +from oemof.network import Node from oemof.tools import debugging from oemof.tools import economics from pyomo.core.base.block import ScalarBlock @@ -40,7 +40,7 @@ from oemof.solph._plumbing import sequence as solph_sequence -class GenericStorage(network.Component): +class GenericStorage(Node): r""" Component `GenericStorage` to model with basic characteristics of storages. diff --git a/src/oemof/solph/components/_link.py b/src/oemof/solph/components/_link.py index e4b2c47f2..f48a04209 100644 --- a/src/oemof/solph/components/_link.py +++ b/src/oemof/solph/components/_link.py @@ -18,7 +18,7 @@ """ from warnings import warn -from oemof.network import network as on +from oemof.network import Node from oemof.tools import debugging from pyomo.core import Set from pyomo.core.base.block import ScalarBlock @@ -29,7 +29,7 @@ from oemof.solph._plumbing import sequence -class Link(on.Transformer): +class Link(Node): """A Link object with 2 inputs and 2 outputs. Parameters diff --git a/src/oemof/solph/components/_offset_converter.py b/src/oemof/solph/components/_offset_converter.py index d73165d6a..606b0f3ad 100644 --- a/src/oemof/solph/components/_offset_converter.py +++ b/src/oemof/solph/components/_offset_converter.py @@ -21,7 +21,7 @@ from warnings import warn -from oemof.network import network +from oemof.network import Node from pyomo.core import BuildAction from pyomo.core.base.block import ScalarBlock from pyomo.environ import Constraint @@ -30,7 +30,7 @@ from oemof.solph._plumbing import sequence -class OffsetConverter(network.Transformer): +class OffsetConverter(Node): """An object with one input and one output and two coefficients to model part load behaviour. diff --git a/src/oemof/solph/components/_sink.py b/src/oemof/solph/components/_sink.py index 883dda31a..1890ec7d0 100644 --- a/src/oemof/solph/components/_sink.py +++ b/src/oemof/solph/components/_sink.py @@ -15,11 +15,11 @@ """ from warnings import warn -from oemof.network import network as on +from oemof.network import Node from oemof.tools import debugging -class Sink(on.Sink): +class Sink(Node): """A component which is designed for one input flow. Parameters diff --git a/src/oemof/solph/components/_source.py b/src/oemof/solph/components/_source.py index 287c8d2b5..fae32697f 100644 --- a/src/oemof/solph/components/_source.py +++ b/src/oemof/solph/components/_source.py @@ -16,11 +16,11 @@ from warnings import warn -from oemof.network import network as on +from oemof.network import Node from oemof.tools import debugging -class Source(on.Source): +class Source(Node): """A component which is designed for one output flow. Parameters diff --git a/src/oemof/solph/components/experimental/_generic_caes.py b/src/oemof/solph/components/experimental/_generic_caes.py index 25948b5bc..69e4d5643 100644 --- a/src/oemof/solph/components/experimental/_generic_caes.py +++ b/src/oemof/solph/components/experimental/_generic_caes.py @@ -17,7 +17,7 @@ """ -from oemof.network import network as on +from oemof.network import Node from pyomo.core.base.block import ScalarBlock from pyomo.environ import Binary from pyomo.environ import Constraint @@ -26,7 +26,7 @@ from pyomo.environ import Var -class GenericCAES(on.Transformer): +class GenericCAES(Node): """ Component `GenericCAES` to model arbitrary compressed air energy storages. diff --git a/src/oemof/solph/components/experimental/_piecewise_linear_converter.py b/src/oemof/solph/components/experimental/_piecewise_linear_converter.py index ebdf47349..6d6b68c9b 100644 --- a/src/oemof/solph/components/experimental/_piecewise_linear_converter.py +++ b/src/oemof/solph/components/experimental/_piecewise_linear_converter.py @@ -17,7 +17,7 @@ """ -from oemof.network import network as on +from oemof.network import Node from pyomo.core.base.block import ScalarBlock from pyomo.environ import BuildAction from pyomo.environ import Constraint @@ -26,7 +26,7 @@ from pyomo.environ import Var -class PiecewiseLinearConverter(on.Transformer): +class PiecewiseLinearConverter(Node): """Component to model an energy converter with one input and one output and an arbitrary piecewise linear conversion function. diff --git a/src/oemof/solph/flows/_flow.py b/src/oemof/solph/flows/_flow.py index 03b929575..964f570d1 100644 --- a/src/oemof/solph/flows/_flow.py +++ b/src/oemof/solph/flows/_flow.py @@ -23,14 +23,14 @@ from warnings import warn import numpy as np -from oemof.network import network as on +from oemof.network import Edge from oemof.tools import debugging from oemof.solph._options import Investment from oemof.solph._plumbing import sequence -class Flow(on.Edge): +class Flow(Edge): r"""Defines a flow between two nodes. Keyword arguments are used to set the attributes of this flow. Parameters From ecb8c25c76101751c14002f1be320810888ad667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 18:21:46 +0200 Subject: [PATCH 037/180] Use pytest.approx(x) instead of int(round(x)) --- .../test_connect_invest/test_connect_invest.py | 11 ++++++----- .../test_solph/test_generic_caes/test_generic_caes.py | 3 ++- .../test_solph/test_generic_chp/test_generic_chp.py | 3 ++- tests/test_scripts/test_solph/test_lopf/test_lopf.py | 5 +++-- .../test_simple_model/test_simple_dispatch.py | 3 ++- .../test_simple_model/test_simple_dispatch_one.py | 4 +++- .../test_simple_dispatch_one_explicit_timemode.py | 4 +++- .../test_simple_model/test_simple_invest.py | 3 ++- .../test_storage_investment.py | 3 ++- .../test_storage_with_tuple_label.py | 11 +++++++---- .../test_solph/test_variable_chp/test_variable_chp.py | 9 +++++---- 11 files changed, 37 insertions(+), 22 deletions(-) diff --git a/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py b/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py index 91637d424..f2bdfbc98 100644 --- a/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py +++ b/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py @@ -12,6 +12,7 @@ import logging import os +import pytest import pandas as pd @@ -131,11 +132,11 @@ def test_connect_invest(): stor_res = views.node(results, "storage")["scalars"] my_results["storage_in"] = stor_res[ [(("electricity1", "storage"), "invest")] - ] - my_results["storage"] = stor_res[[(("storage", "None"), "invest")]] + ].iloc[0] + my_results["storage"] = stor_res[[(("storage", "None"), "invest")]].iloc[0] my_results["storage_out"] = stor_res[ [(("storage", "electricity1"), "invest")] - ] + ].iloc[0] connect_invest_dict = { "line12": 814705, @@ -146,6 +147,6 @@ def test_connect_invest(): } for key in connect_invest_dict.keys(): - assert int(round(my_results[key])) == int( - round(connect_invest_dict[key]) + assert my_results[key] == pytest.approx( + connect_invest_dict[key], abs=0.5 ) diff --git a/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py b/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py index 281637777..a4a907ba4 100644 --- a/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py +++ b/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py @@ -15,6 +15,7 @@ import os import pandas as pd +import pytest from oemof.solph import EnergySystem from oemof.solph import Model @@ -140,4 +141,4 @@ def test_gen_caes(): } for key in test_dict.keys(): - assert int(round(data[key])) == int(round(test_dict[key])) + assert data[key] == pytest.approx(test_dict[key]) diff --git a/tests/test_scripts/test_solph/test_generic_chp/test_generic_chp.py b/tests/test_scripts/test_solph/test_generic_chp/test_generic_chp.py index 175157200..54c2744af 100644 --- a/tests/test_scripts/test_solph/test_generic_chp/test_generic_chp.py +++ b/tests/test_scripts/test_solph/test_generic_chp/test_generic_chp.py @@ -15,6 +15,7 @@ import os import pandas as pd +import pytest from oemof import solph as solph from oemof.solph import processing @@ -124,4 +125,4 @@ def test_gen_chp(): } for key in test_dict.keys(): - assert int(round(data[key])) == int(round(test_dict[key])) + assert data[key] == pytest.approx(test_dict[key]) diff --git a/tests/test_scripts/test_solph/test_lopf/test_lopf.py b/tests/test_scripts/test_solph/test_lopf/test_lopf.py index f3ea9f649..3b36fdf28 100644 --- a/tests/test_scripts/test_solph/test_lopf/test_lopf.py +++ b/tests/test_scripts/test_solph/test_lopf/test_lopf.py @@ -15,6 +15,7 @@ import logging import pandas as pd +import pytest from oemof.solph import EnergySystem from oemof.solph import Investment @@ -124,8 +125,8 @@ def test_lopf(solver="cbc"): for key in generators_test_results.keys(): logging.debug("Test genertor production of {0}".format(key)) - assert int(round(generators[key])) == int( - round(generators_test_results[key]) + assert generators[key].iloc[0] == pytest.approx( + generators_test_results[key] ) assert ( diff --git a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch.py b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch.py index ee694a772..44da686c7 100644 --- a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch.py +++ b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch.py @@ -16,6 +16,7 @@ import os import pandas as pd +import pytest from oemof.solph import EnergySystem from oemof.solph import Model @@ -190,4 +191,4 @@ def test_dispatch_example(solver="cbc", periods=24 * 5): } for key in test_results.keys(): - assert int(round(results[key])) == int(round(test_results[key])) + assert results[key] == pytest.approx(test_results[key], abs=0.5) diff --git a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one.py b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one.py index d7e4c3a6c..bb4d30d20 100644 --- a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one.py +++ b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one.py @@ -11,6 +11,8 @@ SPDX-License-Identifier: MIT """ +import pytest + from oemof.solph import EnergySystem from oemof.solph import Model from oemof.solph import processing @@ -116,4 +118,4 @@ def test_dispatch_one_time_step(solver="cbc"): } for key in test_results.keys(): - assert int(round(results[key])) == int(round(test_results[key])) + assert results[key] == pytest.approx(test_results[key], abs=0.5) diff --git a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one_explicit_timemode.py b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one_explicit_timemode.py index d7e4c3a6c..bb4d30d20 100644 --- a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one_explicit_timemode.py +++ b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one_explicit_timemode.py @@ -11,6 +11,8 @@ SPDX-License-Identifier: MIT """ +import pytest + from oemof.solph import EnergySystem from oemof.solph import Model from oemof.solph import processing @@ -116,4 +118,4 @@ def test_dispatch_one_time_step(solver="cbc"): } for key in test_results.keys(): - assert int(round(results[key])) == int(round(test_results[key])) + assert results[key] == pytest.approx(test_results[key], abs=0.5) diff --git a/tests/test_scripts/test_solph/test_simple_model/test_simple_invest.py b/tests/test_scripts/test_solph/test_simple_model/test_simple_invest.py index 5a60a3e61..a1d53601a 100644 --- a/tests/test_scripts/test_solph/test_simple_model/test_simple_invest.py +++ b/tests/test_scripts/test_solph/test_simple_model/test_simple_invest.py @@ -16,6 +16,7 @@ import os import pandas as pd +import pytest from oemof.tools import economics from oemof.solph import EnergySystem @@ -208,4 +209,4 @@ def test_dispatch_example(solver="cbc", periods=24 * 5): } for key in test_results.keys(): - assert int(round(comp_results[key])) == int(round(test_results[key])) + assert comp_results[key] == pytest.approx(test_results[key], abs=0.5) diff --git a/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py b/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py index a22ec81bb..3772edddc 100644 --- a/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py +++ b/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py @@ -38,6 +38,7 @@ import os import pandas as pd +import pytest from oemof.tools import economics from oemof import solph @@ -179,7 +180,7 @@ def test_results_with_actual_dump(): } for key in stor_invest_dict.keys(): - assert int(round(my_results[key])) == int(round(stor_invest_dict[key])) + assert my_results[key] == pytest.approx(stor_invest_dict[key]) # Solver results assert str(meta["solver"]["Termination condition"]) == "optimal" diff --git a/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py b/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py index 845820fcf..2c38fcdb6 100644 --- a/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py +++ b/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py @@ -36,6 +36,7 @@ import logging import os +import pytest from collections import namedtuple import pandas as pd @@ -171,9 +172,11 @@ def test_tuples_as_labels_example( my_results = electricity_bus["sequences"].sum(axis=0).to_dict() storage = es.groups["storage_electricity_battery"] storage_node = views.node(results, storage) - my_results["max_load"] = storage_node["sequences"].max()[ - [((storage, None), "storage_content")] - ] + my_results["max_load"] = ( + storage_node["sequences"] + .max()[[((storage, None), "storage_content")]] + .iloc[0] + ) commodity_bus = views.node(results, "bus_natural_gas_None") gas_usage = commodity_bus["sequences"][ @@ -201,7 +204,7 @@ def test_tuples_as_labels_example( } for key in stor_invest_dict.keys(): - assert int(round(my_results[key])) == int(round(stor_invest_dict[key])) + assert my_results[key] == pytest.approx(stor_invest_dict[key]) # Solver results assert str(meta["solver"]["Termination condition"]) == "optimal" diff --git a/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py b/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py index 59b940a82..918249e7e 100644 --- a/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py +++ b/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py @@ -16,6 +16,7 @@ import os import pandas as pd +import pytest from oemof import solph from oemof.solph import views @@ -172,14 +173,14 @@ def test_variable_chp(filename="variable_chp.csv", solver="cbc"): for key in variable_chp_dict_max.keys(): logging.debug("Test the maximum value of {0}".format(key)) - assert int(round(maxresults[[key]])) == int( - round(variable_chp_dict_max[key]) + assert maxresults[[key]].iloc[0] == pytest.approx( + variable_chp_dict_max[key] ) for key in variable_chp_dict_sum.keys(): logging.debug("Test the summed up value of {0}".format(key)) - assert int(round(sumresults[[key]])) == int( - round(variable_chp_dict_sum[key]) + assert sumresults[[key]].iloc[0] == pytest.approx( + variable_chp_dict_sum[key] ) assert ( From 3e02fc59e987553b6baae77fa1850c237ac72748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 22:10:05 +0200 Subject: [PATCH 038/180] Embrace conformity * pytest.approx instead of roundin * series.iloc[int] instead of series[int] --- tests/test_non_equidistant_time_index.py | 37 ++++++++++--------- tests/test_processing.py | 24 +++++++----- .../test_solph/test_lopf/test_lopf.py | 16 ++++++-- .../test_storage_investment.py | 2 +- .../test_storage_with_tuple_label.py | 2 +- .../test_variable_chp/test_variable_chp.py | 4 +- tests/test_solph_network_classes.py | 14 ++++--- 7 files changed, 60 insertions(+), 39 deletions(-) diff --git a/tests/test_non_equidistant_time_index.py b/tests/test_non_equidistant_time_index.py index 488e826ef..60da70a97 100644 --- a/tests/test_non_equidistant_time_index.py +++ b/tests/test_non_equidistant_time_index.py @@ -10,6 +10,7 @@ import random import pandas as pd +import pytest from oemof.solph import EnergySystem from oemof.solph import Investment @@ -84,7 +85,7 @@ def test_timesteps_timeincrements_with_storage_charging(self): for k, v in self.comp.items() if k[0].label == "storage" ][0] - assert storage_content[0] == storage_content[-1] + assert storage_content.iloc[0] == storage_content.iloc[-1] charge = [ v["sequences"]["flow"] @@ -96,9 +97,9 @@ def test_timesteps_timeincrements_with_storage_charging(self): # Charging - timestep (ts) with its timeincrement (ti) time = [(23, 1), (24, 0.5)] for ts, ti in time: - assert round(storage_content[ts] + charge[ts] * ti, 5) == round( - storage_content[ts + 1], 5 - ) + assert storage_content.iloc[ts] + charge.iloc[ + ts + ] * ti == pytest.approx(storage_content.iloc[ts + 1]) assert self.es.timeincrement[ts] == ti assert charge.isnull().any() @@ -110,7 +111,7 @@ def test_timesteps_timeincrements_with_storage_discharging(self): ][0] # Storage content at the last time point is equal to the content of # the first time point because the storage is balanced. - assert storage_content[0] == storage_content[-1] + assert storage_content.iloc[0] == storage_content.iloc[-1] discharge = [ v["sequences"]["flow"] @@ -123,11 +124,10 @@ def test_timesteps_timeincrements_with_storage_discharging(self): # Discharging - timestep (ts) with its timeincrement (ti) time = [(7, 1), (40, 0.5)] for ts, ti in time: - assert round( - storage_content[ts] - - (discharge[ts] + (discharge[ts] * 1 / 9)) * ti, - 5, - ) == round(storage_content[ts + 1], 5) + assert ( + storage_content.iloc[ts] + - (discharge.iloc[ts] + (discharge.iloc[ts] * 1 / 9)) * ti + ) == pytest.approx(storage_content.iloc[ts + 1]) assert self.es.timeincrement[ts] == ti def test_timeincrements(self): @@ -150,8 +150,11 @@ def test_without_last_time_point(self): # The first and the last value are not the same because the last value # of the storage is missing. Adding the charging of the last time step # will result the final storage content, which is equal to the first - assert storage_content[0] != storage_content[-1] - assert storage_content[0] == storage_content[-1] + charge[-1] / 2 + assert storage_content.iloc[0] != storage_content.iloc[-1] + assert ( + storage_content.iloc[0] + == storage_content.iloc[-1] + charge.iloc[-1] / 2 + ) assert not charge.isnull().any() assert storage_content.index[0] == datetime.datetime( 2012, 1, 1, 0, 0, 0 @@ -168,7 +171,7 @@ def test_time_index_with_last_time_point(self): for k, v in self.comp.items() if k[0].label == "storage" ][0] - assert storage_content[0] == storage_content[-1] + assert storage_content.iloc[0] == storage_content.iloc[-1] charge = [ v["sequences"]["flow"] @@ -205,7 +208,7 @@ def test_numeric_index(self): for k, v in self.comp.items() if k[0].label == "storage" ][0] - assert storage_content[0] == storage_content[-1] + assert storage_content.iloc[0] == storage_content.iloc[-1] charge = [ v["sequences"]["flow"] @@ -217,8 +220,8 @@ def test_numeric_index(self): # Charging - timestep (ts) with its timeincrement (ti) time = [(23, 1), (24, 0.5)] for ts, ti in time: - assert round(storage_content[ts] + charge[ts] * ti, 5) == round( - storage_content[ts + 1], 5 - ) + assert ( + storage_content.iloc[ts] + charge.iloc[ts] * ti + ) == pytest.approx(storage_content.iloc[ts + 1]) assert self.es.timeincrement[ts] == ti assert charge.isnull().any() diff --git a/tests/test_processing.py b/tests/test_processing.py index 6cc68ccc2..ae0695ae4 100644 --- a/tests/test_processing.py +++ b/tests/test_processing.py @@ -301,7 +301,9 @@ def test_node_weight_by_type(self): storage_content = views.node_weight_by_type( results, node_type=GenericStorage ) - assert round(float(storage_content.sum()), 1) == 1437.5 + assert ( + storage_content.sum().iloc[0] == pytest.approx(1437.5, abs=0.1) + ).all() def test_output_by_type_view(self): results = processing.results(self.om) @@ -311,13 +313,13 @@ def test_output_by_type_view(self): compare = views.node(results, "diesel", multiindex=True)["sequences"][ ("diesel", "b_el1", "flow") ] - assert int(converter_output.sum()) == int(compare.sum()) + assert converter_output.sum().iloc[0] == pytest.approx(compare.sum()) def test_input_by_type_view(self): results = processing.results(self.om) sink_input = views.node_input_by_type(results, node_type=Sink) compare = views.node(results, "demand_el", multiindex=True) - assert int(sink_input.sum()) == int( + assert sink_input.sum().iloc[0] == pytest.approx( compare["sequences"][("b_el2", "demand_el", "flow")].sum() ) @@ -331,13 +333,17 @@ def test_net_storage_flow(self): assert ( ( - compare[("storage", "b_el2", "flow")] - - compare[("b_el1", "storage", "flow")] + ( + compare[("storage", "b_el2", "flow")] + - compare[("b_el1", "storage", "flow")] + ) + .to_frame() + .fillna(0) + == storage_flow.values ) - .to_frame() - .fillna(0) - == storage_flow.values - ).all()[0] + .all() + .iloc[0] + ) def test_output_by_type_view_empty(self): results = processing.results(self.om) diff --git a/tests/test_scripts/test_solph/test_lopf/test_lopf.py b/tests/test_scripts/test_solph/test_lopf/test_lopf.py index 3b36fdf28..beccd909a 100644 --- a/tests/test_scripts/test_solph/test_lopf/test_lopf.py +++ b/tests/test_scripts/test_solph/test_lopf/test_lopf.py @@ -130,19 +130,27 @@ def test_lopf(solver="cbc"): ) assert ( - results[es.groups["b_2"], es.groups["b_0"]]["sequences"]["flow"][0] + results[es.groups["b_2"], es.groups["b_0"]]["sequences"]["flow"].iloc[ + 0 + ] == -40 ) assert ( - results[es.groups["b_1"], es.groups["b_2"]]["sequences"]["flow"][0] + results[es.groups["b_1"], es.groups["b_2"]]["sequences"]["flow"].iloc[ + 0 + ] == 60 ) assert ( - results[es.groups["b_0"], es.groups["b_1"]]["sequences"]["flow"][0] + results[es.groups["b_0"], es.groups["b_1"]]["sequences"]["flow"].iloc[ + 0 + ] == -20 ) # objective function - assert round(processing.meta_results(om)["objective"]) == 3200 + assert processing.meta_results(om)["objective"] == pytest.approx( + 3200, abs=0.5 + ) diff --git a/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py b/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py index 3772edddc..0975a8d15 100644 --- a/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py +++ b/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py @@ -197,7 +197,7 @@ def test_results_with_actual_dump(): assert str(meta["problem"]["Sense"]) == "minimize" # Objective function - assert round(meta["objective"]) == 423167578261115584 + assert meta["objective"] == pytest.approx(423167578261115584, abs=0.5) def test_solph_converter_attributes_before_dump_and_after_restore(): diff --git a/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py b/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py index 2c38fcdb6..6ddbf5c18 100644 --- a/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py +++ b/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py @@ -221,4 +221,4 @@ def test_tuples_as_labels_example( assert str(meta["problem"]["Sense"]) == "minimize" # Objective function - assert round(meta["objective"]) == 37819254 + assert meta["objective"] == pytest.approx(37819254, abs=0.5) diff --git a/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py b/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py index 918249e7e..4af4e53fa 100644 --- a/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py +++ b/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py @@ -197,4 +197,6 @@ def test_variable_chp(filename="variable_chp.csv", solver="cbc"): ) # objective function - assert round(solph.processing.meta_results(om)["objective"]) == 326661590 + assert solph.processing.meta_results(om)["objective"] == pytest.approx( + 326661590, abs=0.5 + ) diff --git a/tests/test_solph_network_classes.py b/tests/test_solph_network_classes.py index 24c540a62..efd868279 100644 --- a/tests/test_solph_network_classes.py +++ b/tests/test_solph_network_classes.py @@ -22,12 +22,8 @@ class TestConverterClass: def setup_class(cls): """Setup default values""" cls.bus = solph.buses.Bus() - warnings.filterwarnings("ignore", category=SuspiciousUsageWarning) - - @classmethod - def teardown_class(cls): - warnings.filterwarnings("always", category=SuspiciousUsageWarning) + @pytest.mark.filterwarnings("ignore::UserWarning") def test_empty_converter(self): transf = solph.components.Converter() assert isinstance(transf.conversion_factors, dict) @@ -35,13 +31,15 @@ def test_empty_converter(self): def test_default_conversion_factor(self): transf = solph.components.Converter( - inputs={self.bus: solph.flows.Flow()} + inputs={self.bus: solph.flows.Flow()}, + outputs={self.bus: solph.flows.Flow()}, ) assert transf.conversion_factors[self.bus][2] == 1 def test_sequence_conversion_factor_from_scalar(self): transf = solph.components.Converter( inputs={self.bus: solph.flows.Flow()}, + outputs={self.bus: solph.flows.Flow()}, conversion_factors={self.bus: 2}, ) assert transf.conversion_factors[self.bus][6] == 2 @@ -49,6 +47,7 @@ def test_sequence_conversion_factor_from_scalar(self): def test_sequence_conversion_factor_from_list_correct_length(self): transf = solph.components.Converter( inputs={self.bus: solph.flows.Flow()}, + outputs={self.bus: solph.flows.Flow()}, conversion_factors={self.bus: [2]}, ) assert len(transf.conversion_factors[self.bus]) == 1 @@ -56,15 +55,18 @@ def test_sequence_conversion_factor_from_list_correct_length(self): def test_sequence_conversion_factor_from_list_wrong_length(self): transf = solph.components.Converter( inputs={self.bus: solph.flows.Flow()}, + outputs={self.bus: solph.flows.Flow()}, conversion_factors={self.bus: [2]}, ) with pytest.raises(IndexError): self.a = transf.conversion_factors[self.bus][6] + @pytest.mark.filterwarnings("ignore:Attribute :UserWarning") def test_converter_missing_output_create_empty_dict(self): trfr = solph.components.Converter(inputs={}) assert trfr.outputs == {} + @pytest.mark.filterwarnings("ignore:Attribute :UserWarning") def test_converter_missing_input_create_empty_dict(self): trfr = solph.components.Converter(outputs={}) assert trfr.inputs == {} From 962abb60fd90f21ae36bd278b715d4570c11ea92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 22:26:27 +0200 Subject: [PATCH 039/180] Use full_load_time_min instead of summed_min --- tests/constraint_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/constraint_tests.py b/tests/constraint_tests.py index 53a35936e..55a7e3027 100644 --- a/tests/constraint_tests.py +++ b/tests/constraint_tests.py @@ -1860,8 +1860,8 @@ def test_summed_min_max_source(self): label="excess", inputs={ bel: solph.flows.Flow( - summed_min=3, - summed_max=100, + full_load_time_min=3, + full_load_time_max=100, variable_costs=25, max=0.8, nominal_value=10, From aa43b30ad3a235fd692453e35101a51058c42d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 22:28:08 +0200 Subject: [PATCH 040/180] Sort imports --- .../test_solph/test_connect_invest/test_connect_invest.py | 2 +- .../test_storage_investment/test_storage_with_tuple_label.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py b/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py index f2bdfbc98..9bff4ad64 100644 --- a/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py +++ b/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py @@ -12,9 +12,9 @@ import logging import os -import pytest import pandas as pd +import pytest from oemof.solph import EnergySystem from oemof.solph import Investment diff --git a/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py b/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py index 6ddbf5c18..9efa8ed88 100644 --- a/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py +++ b/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py @@ -36,10 +36,10 @@ import logging import os -import pytest from collections import namedtuple import pandas as pd +import pytest from oemof import solph as solph from oemof.solph import processing From 01564779e0d33135ebabb9fedebc171a001de325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 11 Oct 2023 22:31:59 +0200 Subject: [PATCH 041/180] Delete unused import --- tests/test_solph_network_classes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_solph_network_classes.py b/tests/test_solph_network_classes.py index efd868279..fa403541a 100644 --- a/tests/test_solph_network_classes.py +++ b/tests/test_solph_network_classes.py @@ -12,7 +12,6 @@ import warnings import pytest -from oemof.tools.debugging import SuspiciousUsageWarning from oemof import solph From 7ffcda291845232db702a3a3d4a2b7de15f4d042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 11:52:22 +0200 Subject: [PATCH 042/180] Fix error message in GenericStorage --- src/oemof/solph/components/_generic_storage.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index c24ddd2f8..831d8989f 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -201,7 +201,8 @@ def __init__( if investment is not None: msg = ( "For backward compatibility," - " the option investment overwrites the option nominal_value." + " the option investment overwrites the option" + + " nominal_storage_capacity." + " Both options cannot be set at the same time." ) if nominal_storage_capacity is not None: From 63e699ee3a9d244579b2ce1d6e31926ccf32edfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 14:02:25 +0200 Subject: [PATCH 043/180] Change deprecated API calls --- docs/usage.rst | 17 ++- examples/electrical/lopf.py | 2 +- examples/electrical/transshipment.py | 4 +- .../example_generic_invest.py | 6 +- .../diesel_genset_nonconvex_investment.py | 17 +-- .../house_with_nonconvex_investment.py | 2 +- .../house_without_nonconvex_investment.py | 2 +- .../minimal_invest.py | 3 +- ...fset_diesel_genset_nonconvex_investment.py | 17 +-- .../v1_invest_optimize_all_technologies.py | 6 +- ...v2_invest_optimize_only_gas_and_storage.py | 2 +- ...optimize_only_storage_with_fossil_share.py | 2 +- ...mize_all_technologies_with_fossil_share.py | 4 +- src/oemof/solph/_energy_system.py | 6 +- .../solph/components/_generic_storage.py | 2 +- .../solph/constraints/equate_variables.py | 4 +- .../solph/constraints/investment_limit.py | 4 +- tests/constraint_tests.py | 113 ++++++++++-------- tests/multi_period_constraint_tests.py | 104 ++++++++-------- tests/test_components.py | 27 +++-- tests/test_constraints_module.py | 13 +- tests/test_energy_system.py | 4 +- tests/test_grouping.py | 2 +- tests/test_models.py | 4 +- tests/test_non_equidistant_time_index.py | 2 +- tests/test_options.py | 4 +- tests/test_outputlib/__init__.py | 2 +- tests/test_processing.py | 11 +- .../test_connect_invest.py | 26 ++-- .../test_add_constraints.py | 5 +- .../test_generic_caes/test_generic_caes.py | 2 +- .../test_generic_chp/test_generic_chp.py | 2 +- .../test_simple_invest_fixed.py | 6 +- .../test_solph/test_lopf/test_lopf.py | 4 +- .../test_multi_period_investment_model.py | 14 +-- .../test_piecewiselineartransformer.py | 4 +- .../test_simple_model/test_simple_dispatch.py | 4 +- .../test_simple_model/test_simple_invest.py | 8 +- .../test_invest_storage_regression.py | 13 +- .../test_storage_investment.py | 10 +- .../test_storage_with_tuple_label.py | 5 +- .../test_variable_chp/test_variable_chp.py | 4 +- tests/test_time_index.py | 10 +- tests/test_warnings.py | 3 +- 44 files changed, 277 insertions(+), 229 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index 32b8e3741..fe60ea434 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -643,8 +643,8 @@ The following example pictures a Pumped Hydroelectric Energy Storage (PHES). Bot solph.components.GenericStorage( label='PHES', - inputs={b_el: solph.flows.Flow(investment= solph.Investment(ep_costs=500))}, - outputs={b_el: solph.flows.Flow(investment= solph.Investment(ep_costs=500)}, + inputs={b_el: solph.flows.Flow(nominal_value= solph.Investment(ep_costs=500))}, + outputs={b_el: solph.flows.Flow(nominal_value= solph.Investment(ep_costs=500)}, loss_rate=0.001, inflow_conversion_factor=0.98, outflow_conversion_factor=0.8), investment = solph.Investment(ep_costs=40)) @@ -912,7 +912,7 @@ turbines. solph.components.Source(label='new_wind_pp', outputs={electricity: solph.flows.Flow( fix=wind_power_time_series, - investment=solph.Investment(ep_costs=epc, maximum=50000))}) + nominal_value=solph.Investment(ep_costs=epc, maximum=50000))}) Let's slightly alter the case and consider for already existing wind power capacity of 20,000 kW. We're still expecting the total wind power capacity, thus we @@ -922,7 +922,7 @@ allow for 30,000 kW of new installations and formulate as follows. solph.components.Source(label='new_wind_pp', outputs={electricity: solph.flows.Flow( fix=wind_power_time_series, - investment=solph.Investment(ep_costs=epc, + nominal_value=solph.Investment(ep_costs=epc, maximum=30000, existing=20000))}) @@ -957,7 +957,7 @@ example of a converter: label='converter_nonconvex', inputs={bus_0: solph.flows.Flow()}, outputs={bus_1: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=4, maximum=100, minimum=20, @@ -1144,7 +1144,7 @@ Here is an example inputs={hydrogen_bus: solph.flows.Flow()}, outputs={ electricity_bus: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( maximum=1000, ep_costs=1e6, lifetime=30, @@ -1178,7 +1178,7 @@ This would mean that for investments in the particular period, these values woul inputs={hydrogen_bus: solph.flows.Flow()}, outputs={ electricity_bus: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( maximum=1000, ep_costs=[1e6, 1.1e6], lifetime=30, @@ -1466,12 +1466,11 @@ This nonlinearity is linearised in the inputs={b_diesel: solph.flows.Flow()}, outputs={ b_el: solph.flows.Flow( - nominal_value=None, variable_costs=0.04, min=0.2, max=1, nonconvex=solph.NonConvex(), - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=90, maximum=150, # required for the linearization ), diff --git a/examples/electrical/lopf.py b/examples/electrical/lopf.py index 33be875c0..b8ab5d210 100644 --- a/examples/electrical/lopf.py +++ b/examples/electrical/lopf.py @@ -151,7 +151,7 @@ def main(): input=b_el0, output=b_el1, reactance=0.0001, - investment=Investment(ep_costs=10), + nominal_value=Investment(ep_costs=10), min=-1, max=1, ) diff --git a/examples/electrical/transshipment.py b/examples/electrical/transshipment.py index 2379da98b..8f6349c72 100644 --- a/examples/electrical/transshipment.py +++ b/examples/electrical/transshipment.py @@ -144,8 +144,8 @@ def main(): label="line_0", inputs={b_0: Flow(), b_1: Flow()}, outputs={ - b_1: Flow(investment=Investment()), - b_0: Flow(investment=Investment()), + b_1: Flow(nominal_value=Investment()), + b_0: Flow(nominal_value=Investment()), }, conversion_factors={(b_0, b_1): 0.95, (b_1, b_0): 0.9}, ) diff --git a/examples/generic_invest_limit/example_generic_invest.py b/examples/generic_invest_limit/example_generic_invest.py index f7b6387bf..841d49e5a 100644 --- a/examples/generic_invest_limit/example_generic_invest.py +++ b/examples/generic_invest_limit/example_generic_invest.py @@ -141,8 +141,7 @@ def main(): inputs={bus_a_0: solph.Flow()}, outputs={ bus_a_1: solph.Flow( - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_invest, custom_attributes={"space": 2}, ), @@ -159,8 +158,7 @@ def main(): inputs={bus_b_0: solph.Flow()}, outputs={ bus_b_1: solph.Flow( - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_invest, custom_attributes={"space": 1}, ), diff --git a/examples/invest_nonconvex_flow_examples/diesel_genset_nonconvex_investment.py b/examples/invest_nonconvex_flow_examples/diesel_genset_nonconvex_investment.py index e90d0f10c..d273d3380 100644 --- a/examples/invest_nonconvex_flow_examples/diesel_genset_nonconvex_investment.py +++ b/examples/invest_nonconvex_flow_examples/diesel_genset_nonconvex_investment.py @@ -132,8 +132,7 @@ def main(): outputs={ b_el_dc: solph.flows.Flow( fix=solar_potential / peak_solar_potential, - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_pv * n_days / n_days_in_year ), variable_costs=0, @@ -157,11 +156,10 @@ def main(): inputs={b_diesel: solph.flows.Flow()}, outputs={ b_el_ac: solph.flows.Flow( - nominal_value=None, variable_costs=variable_cost_diesel_genset, min=min_load, max=max_load, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_diesel_genset * n_days / n_days_in_year, maximum=2 * peak_demand, ), @@ -177,8 +175,7 @@ def main(): label="rectifier", inputs={ b_el_ac: solph.flows.Flow( - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_rectifier * n_days / n_days_in_year ), variable_costs=0, @@ -196,8 +193,7 @@ def main(): label="inverter", inputs={ b_el_dc: solph.flows.Flow( - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_inverter * n_days / n_days_in_year ), variable_costs=0, @@ -213,13 +209,12 @@ def main(): epc_battery = 101.00 # currency/kWh/year battery = solph.components.GenericStorage( label="battery", - nominal_storage_capacity=None, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=epc_battery * n_days / n_days_in_year ), inputs={b_el_dc: solph.flows.Flow(variable_costs=0)}, outputs={ - b_el_dc: solph.flows.Flow(investment=solph.Investment(ep_costs=0)) + b_el_dc: solph.flows.Flow(nominal_value=solph.Investment(ep_costs=0)) }, initial_storage_level=0.0, min_storage_level=0.0, diff --git a/examples/invest_nonconvex_flow_examples/house_with_nonconvex_investment.py b/examples/invest_nonconvex_flow_examples/house_with_nonconvex_investment.py index e8fbb1458..ba50494ab 100644 --- a/examples/invest_nonconvex_flow_examples/house_with_nonconvex_investment.py +++ b/examples/invest_nonconvex_flow_examples/house_with_nonconvex_investment.py @@ -91,7 +91,7 @@ def heat_demand(d): minimum_uptime=5, initial_status=1, ), - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc, minimum=1.0, maximum=10.0, diff --git a/examples/invest_nonconvex_flow_examples/house_without_nonconvex_investment.py b/examples/invest_nonconvex_flow_examples/house_without_nonconvex_investment.py index cca936cce..15baeacf3 100644 --- a/examples/invest_nonconvex_flow_examples/house_without_nonconvex_investment.py +++ b/examples/invest_nonconvex_flow_examples/house_without_nonconvex_investment.py @@ -117,7 +117,7 @@ def solar_thermal(d): outputs={ b_heat: solph.flows.Flow( fix=[solar_thermal(day) for day in range(0, periods)], - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc, minimum=1.0, maximum=5.0 ), ) diff --git a/examples/investment_with_minimal_invest/minimal_invest.py b/examples/investment_with_minimal_invest/minimal_invest.py index 8e9944ede..6302fa816 100644 --- a/examples/investment_with_minimal_invest/minimal_invest.py +++ b/examples/investment_with_minimal_invest/minimal_invest.py @@ -86,8 +86,7 @@ def main(): inputs={bus_0: solph.Flow()}, outputs={ bus_1: solph.Flow( - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=c_var, maximum=p_install_max, minimum=p_install_min, diff --git a/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py b/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py index 38e8cccf9..15e5164ae 100644 --- a/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py +++ b/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py @@ -127,8 +127,7 @@ def offset_converter_example(): outputs={ b_el_dc: solph.flows.Flow( fix=solar_potential / peak_solar_potential, - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_pv * n_days / n_days_in_year ), variable_costs=0, @@ -168,11 +167,10 @@ def offset_converter_example(): inputs={b_diesel: solph.flows.Flow()}, outputs={ b_el_ac: solph.flows.Flow( - nominal_value=None, variable_costs=variable_cost_diesel_genset, min=min_load, max=max_load, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_diesel_genset * n_days / n_days_in_year, maximum=2 * peak_demand, ), @@ -188,8 +186,7 @@ def offset_converter_example(): label="rectifier", inputs={ b_el_ac: solph.flows.Flow( - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_rectifier * n_days / n_days_in_year ), variable_costs=0, @@ -207,8 +204,7 @@ def offset_converter_example(): label="inverter", inputs={ b_el_dc: solph.flows.Flow( - nominal_value=None, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=epc_inverter * n_days / n_days_in_year ), variable_costs=0, @@ -224,13 +220,12 @@ def offset_converter_example(): epc_battery = 101.00 # currency/kWh/year battery = solph.components.GenericStorage( label="battery", - nominal_storage_capacity=None, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=epc_battery * n_days / n_days_in_year ), inputs={b_el_dc: solph.flows.Flow(variable_costs=0)}, outputs={ - b_el_dc: solph.flows.Flow(investment=solph.Investment(ep_costs=0)) + b_el_dc: solph.flows.Flow(nominal_value=solph.Investment(ep_costs=0)) }, initial_storage_level=0.0, min_storage_level=0.0, diff --git a/examples/storage_investment/v1_invest_optimize_all_technologies.py b/examples/storage_investment/v1_invest_optimize_all_technologies.py index 7bb185509..07a139778 100644 --- a/examples/storage_investment/v1_invest_optimize_all_technologies.py +++ b/examples/storage_investment/v1_invest_optimize_all_technologies.py @@ -151,7 +151,7 @@ def main(): outputs={ bel: solph.Flow( fix=data["wind"], - investment=solph.Investment(ep_costs=epc_wind), + nominal_value=solph.Investment(ep_costs=epc_wind), ) }, ) @@ -161,7 +161,7 @@ def main(): label="pv", outputs={ bel: solph.Flow( - fix=data["pv"], investment=solph.Investment(ep_costs=epc_pv) + fix=data["pv"], nominal_value=solph.Investment(ep_costs=epc_pv) ) }, ) @@ -191,7 +191,7 @@ def main(): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - investment=solph.Investment(ep_costs=epc_storage), + nominal_value=solph.Investment(ep_costs=epc_storage), ) energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas, storage) diff --git a/examples/storage_investment/v2_invest_optimize_only_gas_and_storage.py b/examples/storage_investment/v2_invest_optimize_only_gas_and_storage.py index 3e91950c5..b82cef608 100644 --- a/examples/storage_investment/v2_invest_optimize_only_gas_and_storage.py +++ b/examples/storage_investment/v2_invest_optimize_only_gas_and_storage.py @@ -184,7 +184,7 @@ def main(): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - investment=solph.Investment(ep_costs=epc_storage), + nominal_value=solph.Investment(ep_costs=epc_storage), ) energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas, storage) diff --git a/examples/storage_investment/v3_invest_optimize_only_storage_with_fossil_share.py b/examples/storage_investment/v3_invest_optimize_only_storage_with_fossil_share.py index 1046a8d29..7e8c9cc0c 100644 --- a/examples/storage_investment/v3_invest_optimize_only_storage_with_fossil_share.py +++ b/examples/storage_investment/v3_invest_optimize_only_storage_with_fossil_share.py @@ -194,7 +194,7 @@ def main(): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - investment=solph.Investment(ep_costs=epc_storage), + nominal_value=solph.Investment(ep_costs=epc_storage), ) energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas, storage) diff --git a/examples/storage_investment/v4_invest_optimize_all_technologies_with_fossil_share.py b/examples/storage_investment/v4_invest_optimize_all_technologies_with_fossil_share.py index 7c1c89a7b..d25af3f40 100644 --- a/examples/storage_investment/v4_invest_optimize_all_technologies_with_fossil_share.py +++ b/examples/storage_investment/v4_invest_optimize_all_technologies_with_fossil_share.py @@ -162,7 +162,7 @@ def main(): outputs={ bel: solph.Flow( fix=data["wind"], - investment=solph.Investment(ep_costs=epc_wind), + nominal_value=solph.Investment(ep_costs=epc_wind), ) }, ) @@ -172,7 +172,7 @@ def main(): label="pv", outputs={ bel: solph.Flow( - fix=data["pv"], investment=solph.Investment(ep_costs=epc_pv) + fix=data["pv"], nominal_value=solph.Investment(ep_costs=epc_pv) ) }, ) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index a2a166fb5..90125d9ac 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -136,7 +136,7 @@ def __init__( "consistent.\nIf you are not considering non-equidistant " "timeindices, consider only specifying a timeindex." ) - warnings.warn(msg, debugging.SuspiciousUsageWarning) + warnings.warn(msg, debugging.ExperimentalFeatureWarning) elif timeindex is not None and timeincrement is None: df = pd.DataFrame(timeindex) @@ -151,7 +151,7 @@ def __init__( if timeincrement is not None and (pd.Series(timeincrement) <= 0).any(): msg = ( "The time increment is inconsistent. Negative values and zero " - "is not allowed.\nThis is caused by a inconsistent " + "are not allowed.\nThis is caused by a inconsistent " "timeincrement parameter or an incorrect timeindex." ) raise TypeError(msg) @@ -170,7 +170,7 @@ def __init__( "now. If you find anything suspicious or any bugs, " "please report them." ) - warnings.warn(msg, debugging.SuspiciousUsageWarning) + warnings.warn(msg, debugging.ExperimentalFeatureWarning) self.periods = periods self._extract_periods_years() self._extract_periods_matrix() diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index a6156f06a..ef7b37cd6 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -149,7 +149,7 @@ class GenericStorage(Node): >>> my_investment_storage = solph.components.GenericStorage( ... label='storage', - ... investment=solph.Investment(ep_costs=50), + ... nominal_storage_capacity=solph.Investment(ep_costs=50), ... inputs={my_bus: solph.flows.Flow()}, ... outputs={my_bus: solph.flows.Flow()}, ... loss_rate=0.02, diff --git a/src/oemof/solph/constraints/equate_variables.py b/src/oemof/solph/constraints/equate_variables.py index 770062df1..5ce350da4 100644 --- a/src/oemof/solph/constraints/equate_variables.py +++ b/src/oemof/solph/constraints/equate_variables.py @@ -71,12 +71,12 @@ def equate_variables(model, var1, var2, factor1=1, name=None): ... label='powerline_1_2', ... inputs={bel1: solph.flows.Flow()}, ... outputs={bel2: solph.flows.Flow( - ... investment=solph.Investment(ep_costs=20))})) + ... nominal_value=solph.Investment(ep_costs=20))})) >>> energysystem.add(solph.components.Converter( ... label='powerline_2_1', ... inputs={bel2: solph.flows.Flow()}, ... outputs={bel1: solph.flows.Flow( - ... investment=solph.Investment(ep_costs=20))})) + ... nominal_value=solph.Investment(ep_costs=20))})) >>> om = solph.Model(energysystem) >>> line12 = energysystem.groups['powerline_1_2'] >>> line21 = energysystem.groups['powerline_2_1'] diff --git a/src/oemof/solph/constraints/investment_limit.py b/src/oemof/solph/constraints/investment_limit.py index cf6ea8d78..078b553b1 100644 --- a/src/oemof/solph/constraints/investment_limit.py +++ b/src/oemof/solph/constraints/investment_limit.py @@ -178,13 +178,13 @@ def additional_investment_flow_limit(model, keyword, limit=None): ... solph.flows.Flow(nominal_value=10, fix=[10, 20, 30, 40, 50])}) >>> src1 = solph.components.Source( ... label='source_0', outputs={bus: solph.flows.Flow( - ... investment=solph.Investment( + ... nominal_value=solph.Investment( ... ep_costs=50, custom_attributes={"space": 4}, ... )) ... }) >>> src2 = solph.components.Source( ... label='source_1', outputs={bus: solph.flows.Flow( - ... investment=solph.Investment( + ... nominal_value=solph.Investment( ... ep_costs=100, custom_attributes={"space": 1}, ... )) ... }) diff --git a/tests/constraint_tests.py b/tests/constraint_tests.py index 55a7e3027..71cfbd534 100644 --- a/tests/constraint_tests.py +++ b/tests/constraint_tests.py @@ -124,7 +124,7 @@ def test_linear_converter_invest(self): outputs={ bel: solph.flows.Flow( variable_costs=50, - investment=solph.Investment(maximum=1000, ep_costs=20), + nominal_value=solph.Investment(maximum=1000, ep_costs=20), ) }, conversion_factors={bel: 0.58}, @@ -143,11 +143,10 @@ def test_nonconvex_invest_converter(self): inputs={bfuel: solph.flows.Flow()}, outputs={ bel: solph.flows.Flow( - nominal_value=None, variable_costs=25, min=0.25, max=0.5, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, maximum=1234, ), @@ -234,7 +233,7 @@ def test_fixed_source_invest_sink(self): full_load_time_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, maximum=1e6, existing=50 ), ) @@ -254,7 +253,7 @@ def test_invest_source_fixed_sink(self): bel: solph.flows.Flow( max=[45, 83, 65], variable_costs=13, - investment=solph.Investment(ep_costs=123), + nominal_value=solph.Investment(ep_costs=123), ) }, ) @@ -300,7 +299,9 @@ def test_storage_invest_1(self): label="storage1", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, + nominal_storage_capacity=solph.Investment( + ep_costs=145, maximum=234 + ), loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -308,7 +309,6 @@ def test_storage_invest_1(self): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=0.97, outflow_conversion_factor=0.86, - investment=solph.Investment(ep_costs=145, maximum=234), ) self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_1.lp") @@ -320,12 +320,16 @@ def test_storage_invest_2(self): storage = solph.components.GenericStorage( label="storage2", inputs={ - bel: solph.flows.Flow(investment=solph.Investment(ep_costs=99)) + bel: solph.flows.Flow( + nominal_value=solph.Investment(ep_costs=99) + ) }, outputs={ - bel: solph.flows.Flow(investment=solph.Investment(ep_costs=9)) + bel: solph.flows.Flow( + nominal_value=solph.Investment(ep_costs=9) + ) }, - investment=solph.Investment(ep_costs=145), + nominal_storage_capacity=solph.Investment(ep_costs=145), initial_storage_level=0.5, ) self.energysystem.add(bel, storage) @@ -341,10 +345,14 @@ def test_storage_invest_3(self): storage = solph.components.GenericStorage( label="storage3", inputs={ - bel: solph.flows.Flow(investment=solph.Investment(ep_costs=99)) + bel: solph.flows.Flow( + nominal_value=solph.Investment(ep_costs=99) + ) }, outputs={ - bel: solph.flows.Flow(investment=solph.Investment(ep_costs=9)) + bel: solph.flows.Flow( + nominal_value=solph.Investment(ep_costs=9) + ) }, nominal_storage_capacity=5000, ) @@ -359,7 +367,7 @@ def test_storage_invest_4(self): label="storage4", inputs={bel: solph.flows.Flow(nominal_value=80)}, outputs={bel: solph.flows.Flow(nominal_value=100)}, - investment=solph.Investment(ep_costs=145, maximum=500), + nominal_value=solph.Investment(ep_costs=145, maximum=500), ) self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_4.lp") @@ -376,12 +384,12 @@ def test_storage_invest_5(self): label="storage5", inputs={ bel: solph.flows.Flow( - investment=solph.Investment(ep_costs=99, existing=110) + nominal_value=solph.Investment(ep_costs=99, existing=110) ) }, outputs={ bel: solph.flows.Flow( - investment=solph.Investment(existing=100) + nominal_value=solph.Investment(existing=100) ) }, invest_relation_input_output=1.1, @@ -400,16 +408,18 @@ def test_storage_invest_6(self): label="storage6", inputs={ bel: solph.flows.Flow( - investment=solph.Investment(ep_costs=99, existing=110) + nominal_value=solph.Investment(ep_costs=99, existing=110) ) }, outputs={ bel: solph.flows.Flow( - investment=solph.Investment(existing=100) + nominal_value=solph.Investment(existing=100) ) }, invest_relation_input_output=1.1, - investment=solph.Investment(ep_costs=145, existing=10000), + nominal_storage_capacity=solph.Investment( + ep_costs=145, existing=10000 + ), ) self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_6.lp") @@ -424,7 +434,7 @@ def test_storage_minimum_invest(self): label="storage1", inputs={bel: solph.flows.Flow()}, outputs={bel: solph.flows.Flow()}, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=145, minimum=100, maximum=200 ), ) @@ -456,12 +466,11 @@ def test_storage_invest_unbalanced(self): label="storage1", inputs={bel: solph.flows.Flow()}, outputs={bel: solph.flows.Flow()}, - nominal_storage_capacity=None, initial_storage_level=0.5, balanced=False, invest_relation_input_capacity=1, invest_relation_output_capacity=1, - investment=solph.Investment(ep_costs=145), + nominal_value=solph.Investment(ep_costs=145), ) self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_unbalanced.lp") @@ -499,7 +508,6 @@ def test_storage_invest_1_fixed_losses(self): label="storage1", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, fixed_losses_relative=0.01, fixed_losses_absolute=3, @@ -509,7 +517,9 @@ def test_storage_invest_1_fixed_losses(self): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=0.97, outflow_conversion_factor=0.86, - investment=solph.Investment(ep_costs=145, maximum=234), + nominal_storage_capacity=solph.Investment( + ep_costs=145, maximum=234 + ), ) self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_1_fixed_losses.lp") @@ -549,7 +559,7 @@ def test_converter_invest(self): outputs={ bel: solph.flows.Flow( variable_costs=50, - investment=solph.Investment(maximum=1000, ep_costs=20), + nominal_value=solph.Investment(maximum=1000, ep_costs=20), ), bth: solph.flows.Flow(variable_costs=20), }, @@ -573,7 +583,7 @@ def test_converter_invest_with_existing(self): outputs={ bel: solph.flows.Flow( variable_costs=50, - investment=solph.Investment( + nominal_value=solph.Investment( maximum=1000, ep_costs=20, existing=200 ), ), @@ -617,7 +627,7 @@ def test_linear_converter_chp_invest(self): inputs={ bgas: solph.flows.Flow( variable_costs=50, - investment=solph.Investment(maximum=1000, ep_costs=20), + nominal_value=solph.Investment(maximum=1000, ep_costs=20), ) }, outputs={bel: solph.flows.Flow(), bheat: solph.flows.Flow()}, @@ -682,7 +692,7 @@ def test_generic_invest_limit(self): label="source_0", outputs={ bus: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=50, custom_attributes={"space": 4}, ) @@ -694,7 +704,7 @@ def test_generic_invest_limit(self): label="source_1", outputs={ bus: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=100, custom_attributes={"space": 1} ), ) @@ -704,7 +714,9 @@ def test_generic_invest_limit(self): source_2 = solph.components.Source( label="source_2", outputs={ - bus: solph.flows.Flow(investment=solph.Investment(ep_costs=75)) + bus: solph.flows.Flow( + nominal_value=solph.Investment(ep_costs=75) + ) }, ) @@ -897,13 +909,13 @@ def test_equate_variables_constraint(self): invest_relation_output_capacity=0.2, inputs={bus1: solph.flows.Flow()}, outputs={bus1: solph.flows.Flow()}, - investment=solph.Investment(ep_costs=145), + nominal_storage_capacity=solph.Investment(ep_costs=145), ) sink = solph.components.Sink( label="Sink", inputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=500) + nominal_value=solph.Investment(ep_costs=500) ) }, ) @@ -911,7 +923,7 @@ def test_equate_variables_constraint(self): label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123) + nominal_value=solph.Investment(ep_costs=123) ) }, ) @@ -1053,13 +1065,13 @@ def test_investment_limit(self): invest_relation_output_capacity=0.2, inputs={bus1: solph.flows.Flow()}, outputs={bus1: solph.flows.Flow()}, - investment=solph.Investment(ep_costs=145), + nominal_storage_capacity=solph.Investment(ep_costs=145), ) source = solph.components.Source( label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123) + nominal_value=solph.Investment(ep_costs=123) ) }, ) @@ -1076,7 +1088,7 @@ def test_investment_limit_with_dsm1(self): label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123) + nominal_value=solph.Investment(ep_costs=123) ) }, ) @@ -1109,7 +1121,7 @@ def test_investment_limit_with_dsm2(self): label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123) + nominal_value=solph.Investment(ep_costs=123) ) }, ) @@ -1143,7 +1155,7 @@ def test_investment_limit_with_dsm3(self): label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123) + nominal_value=solph.Investment(ep_costs=123) ) }, ) @@ -1179,13 +1191,13 @@ def test_investment_limit_per_period_error_no_multi_period(self): invest_relation_output_capacity=0.2, inputs={bus1: solph.flows.Flow()}, outputs={bus1: solph.flows.Flow()}, - investment=solph.Investment(ep_costs=145), + nominal_storage_capacity=solph.Investment(ep_costs=145), ) solph.components.Source( label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123) + nominal_value=solph.Investment(ep_costs=123) ) }, ) @@ -1371,7 +1383,7 @@ def test_offsetconverter_nonconvex_investment(self): b_el: solph.flows.Flow( min=0.2, nonconvex=solph.NonConvex(), - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=100, maximum=1234, ), @@ -1655,11 +1667,10 @@ def test_invest_non_convex_flow(self): label="b2", inputs={ b1: solph.Flow( - nominal_value=None, variable_costs=8, min=0.25, max=0.5, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=0.75, maximum=10, ), @@ -1681,7 +1692,6 @@ def test_nonconvex_investment_storage_without_offset(self): label="storage_non_convex", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -1689,7 +1699,7 @@ def test_nonconvex_investment_storage_without_offset(self): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=0.97, outflow_conversion_factor=0.86, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=141, maximum=244, minimum=12, nonconvex=True ), ) @@ -1706,7 +1716,6 @@ def test_nonconvex_investment_storage_with_offset(self): label="storage_non_convex", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -1714,7 +1723,7 @@ def test_nonconvex_investment_storage_with_offset(self): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=0.97, outflow_conversion_factor=0.86, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, minimum=19, offset=5, @@ -1733,7 +1742,7 @@ def test_nonconvex_invest_storage_all_nonconvex(self): label="storage_all_nonconvex", inputs={ b1: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( nonconvex=True, minimum=5, offset=10, @@ -1744,7 +1753,7 @@ def test_nonconvex_invest_storage_all_nonconvex(self): }, outputs={ b1: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( nonconvex=True, minimum=8, offset=15, @@ -1753,7 +1762,7 @@ def test_nonconvex_invest_storage_all_nonconvex(self): ) ) }, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( nonconvex=True, ep_costs=20, offset=30, minimum=20, maximum=100 ), ) @@ -1771,7 +1780,7 @@ def test_nonconvex_invest_sink_without_offset(self): full_load_time_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, minimum=15, nonconvex=True, maximum=172 ), ) @@ -1791,7 +1800,7 @@ def test_nonconvex_invest_source_with_offset(self): full_load_time_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, minimum=15, maximum=20, @@ -1815,7 +1824,7 @@ def test_nonconvex_invest_source_with_offset_no_minimum(self): full_load_time_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, maximum=1234, offset=34, nonconvex=True ), ) diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index 2696f5ace..0679a7681 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -131,7 +131,7 @@ def test_linear_converter_invest(self): outputs={ bel: solph.flows.Flow( variable_costs=50, - investment=solph.Investment( + nominal_value=solph.Investment( existing=50, maximum=1000, overall_maximum=10000, @@ -160,7 +160,7 @@ def test_linear_converter_invest_old_capacity(self): outputs={ bel: solph.flows.Flow( variable_costs=50, - investment=solph.Investment( + nominal_value=solph.Investment( existing=50, maximum=1000, overall_maximum=10000, @@ -252,7 +252,7 @@ def test_fixed_source_invest_sink(self): summed_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, maximum=1e6, existing=50, lifetime=20 ), ) @@ -270,7 +270,7 @@ def test_investment_lifetime_missing(self): inputs={ bel: solph.flows.Flow( max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, maximum=1e6, existing=50 ), ) @@ -296,7 +296,7 @@ def test_invest_source_fixed_sink(self): bel: solph.flows.Flow( max=[45, 83, 65, 67, 33, 96], variable_costs=13, - investment=solph.Investment(ep_costs=123, lifetime=25), + nominal_value=solph.Investment(ep_costs=123, lifetime=25), ) }, ) @@ -343,7 +343,6 @@ def test_storage_invest_1(self): label="storage1", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -353,7 +352,7 @@ def test_storage_invest_1(self): lifetime_outflow=20, inflow_conversion_factor=0.97, outflow_conversion_factor=0.86, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, maximum=234, lifetime=20, @@ -373,15 +372,15 @@ def test_storage_invest_2(self): label="storage2", inputs={ bel: solph.flows.Flow( - investment=solph.Investment(ep_costs=99, lifetime=20) + nominal_value=solph.Investment(ep_costs=99, lifetime=20) ) }, outputs={ bel: solph.flows.Flow( - investment=solph.Investment(ep_costs=9, lifetime=20) + nominal_value=solph.Investment(ep_costs=9, lifetime=20) ) }, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, lifetime=20, existing=20, age=19 ), ) @@ -399,7 +398,7 @@ def test_storage_invest_3(self): label="storage3", inputs={ bel: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=99, lifetime=2, age=1, @@ -409,7 +408,7 @@ def test_storage_invest_3(self): }, outputs={ bel: solph.flows.Flow( - investment=solph.Investment(ep_costs=9, lifetime=20) + nominal_value=solph.Investment(ep_costs=9, lifetime=20) ) }, nominal_storage_capacity=5000, @@ -425,7 +424,7 @@ def test_storage_invest_4(self): label="storage4", inputs={bel: solph.flows.Flow(nominal_value=80)}, outputs={bel: solph.flows.Flow(nominal_value=100)}, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, maximum=500, lifetime=2, age=1, existing=100 ), ) @@ -444,14 +443,14 @@ def test_storage_invest_5(self): label="storage5", inputs={ bel: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=99, existing=110, lifetime=20 ) ) }, outputs={ bel: solph.flows.Flow( - investment=solph.Investment(existing=100, lifetime=20) + nominal_value=solph.Investment(existing=100, lifetime=20) ) }, invest_relation_input_output=1.1, @@ -470,18 +469,18 @@ def test_storage_invest_6(self): label="storage6", inputs={ bel: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=99, existing=110, lifetime=20 ) ) }, outputs={ bel: solph.flows.Flow( - investment=solph.Investment(existing=100, lifetime=20) + nominal_value=solph.Investment(existing=100, lifetime=20) ) }, invest_relation_input_output=1.1, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, existing=1000, lifetime=20, age=17 ), ) @@ -498,7 +497,7 @@ def test_storage_minimum_invest(self): label="storage1", inputs={bel: solph.flows.Flow()}, outputs={bel: solph.flows.Flow()}, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, minimum=100, maximum=200, lifetime=40 ), lifetime_inflow=40, @@ -515,7 +514,7 @@ def test_storage_invest_multi_period(self): label="storage1", inputs={bel: solph.flows.Flow()}, outputs={bel: solph.flows.Flow()}, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, minimum=100, maximum=200, @@ -580,7 +579,6 @@ def test_storage_invest_1_fixed_losses(self): label="storage1", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, fixed_losses_relative=0.01, fixed_losses_absolute=3, @@ -592,7 +590,7 @@ def test_storage_invest_1_fixed_losses(self): outflow_conversion_factor=0.86, lifetime_inflow=40, lifetime_outflow=40, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, maximum=234, lifetime=20, @@ -617,7 +615,6 @@ def test_storage_invest_1_initial_storage_level(self): label="storage1", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -628,7 +625,7 @@ def test_storage_invest_1_initial_storage_level(self): lifetime_inflow=40, lifetime_outflow=40, initial_storage_level=0.5, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, maximum=234, lifetime=20, @@ -655,7 +652,6 @@ def test_storage_invest_1_missing_lifetime(self): label="storage1", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -665,7 +661,7 @@ def test_storage_invest_1_missing_lifetime(self): outflow_conversion_factor=0.86, lifetime_inflow=40, lifetime_outflow=40, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, maximum=234, interest_rate=0.05, @@ -714,7 +710,7 @@ def test_converter_invest(self): outputs={ bel: solph.flows.Flow( variable_costs=50, - investment=solph.Investment( + nominal_value=solph.Investment( maximum=1000, ep_costs=20, lifetime=20, @@ -740,7 +736,7 @@ def test_converter_invest_with_existing(self): outputs={ bel: solph.flows.Flow( variable_costs=50, - investment=solph.Investment( + nominal_value=solph.Investment( maximum=1000, ep_costs=20, existing=200, @@ -785,7 +781,7 @@ def test_linear_converter_chp_invest(self): inputs={ bgas: solph.flows.Flow( variable_costs=50, - investment=solph.Investment( + nominal_value=solph.Investment( maximum=1000, ep_costs=20, lifetime=50 ), ) @@ -1031,13 +1027,15 @@ def test_equate_variables_constraint(self): outputs={bus1: solph.flows.Flow()}, lifetime_inflow=3, lifetime_outflow=3, - investment=solph.Investment(ep_costs=145, lifetime=3), + nominal_storage_capacity=solph.Investment( + ep_costs=145, lifetime=3 + ), ) sink = solph.components.Sink( label="Sink", inputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=500, lifetime=3) + nominal_value=solph.Investment(ep_costs=500, lifetime=3) ) }, ) @@ -1045,7 +1043,7 @@ def test_equate_variables_constraint(self): label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123, lifetime=3) + nominal_value=solph.Investment(ep_costs=123, lifetime=3) ) }, ) @@ -1114,13 +1112,15 @@ def test_periodical_investment_limit(self): outputs={bus1: solph.flows.Flow()}, lifetime_inflow=20, lifetime_outflow=20, - investment=solph.Investment(ep_costs=145, lifetime=30), + nominal_storage_capacity=solph.Investment( + ep_costs=145, lifetime=30 + ), ) source = solph.components.Source( label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123, lifetime=100) + nominal_value=solph.Investment(ep_costs=123, lifetime=100) ) }, ) @@ -1139,7 +1139,7 @@ def test_periodical_investment_limit_with_dsm1(self): label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123, lifetime=100) + nominal_value=solph.Investment(ep_costs=123, lifetime=100) ) }, ) @@ -1183,7 +1183,7 @@ def test_periodical_investment_limit_with_dsm2(self): label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123, lifetime=100) + nominal_value=solph.Investment(ep_costs=123, lifetime=100) ) }, ) @@ -1228,7 +1228,7 @@ def test_periodical_investment_limit_with_dsm3(self): label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123, lifetime=100) + nominal_value=solph.Investment(ep_costs=123, lifetime=100) ) }, ) @@ -1277,13 +1277,15 @@ def test_periodical_investment_limit_missing(self): outputs={bus1: solph.flows.Flow()}, lifetime_inflow=20, lifetime_outflow=20, - investment=solph.Investment(ep_costs=145, lifetime=30), + nominal_storage_capacity=solph.Investment( + ep_costs=145, lifetime=30 + ), ) source = solph.components.Source( label="Source", outputs={ bus1: solph.flows.Flow( - investment=solph.Investment(ep_costs=123, lifetime=100) + nominal_value=solph.Investment(ep_costs=123, lifetime=100) ) }, ) @@ -1711,7 +1713,6 @@ def test_nonconvex_investment_storage_without_offset(self): label="storage_non_convex", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -1721,7 +1722,7 @@ def test_nonconvex_investment_storage_without_offset(self): outflow_conversion_factor=0.86, lifetime_inflow=20, lifetime_outflow=20, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=141, maximum=244, minimum=12, @@ -1742,7 +1743,6 @@ def test_nonconvex_investment_storage_with_offset(self): label="storage_non_convex", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -1752,7 +1752,7 @@ def test_nonconvex_investment_storage_with_offset(self): outflow_conversion_factor=0.86, lifetime_inflow=20, lifetime_outflow=20, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, minimum=19, offset=5, @@ -1772,7 +1772,7 @@ def test_nonconvex_invest_storage_all_nonconvex(self): label="storage_all_nonconvex", inputs={ b1: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( nonconvex=True, minimum=5, offset=10, @@ -1784,7 +1784,7 @@ def test_nonconvex_invest_storage_all_nonconvex(self): }, outputs={ b1: solph.flows.Flow( - investment=solph.Investment( + nominal_value=solph.Investment( nonconvex=True, minimum=8, offset=15, @@ -1794,7 +1794,7 @@ def test_nonconvex_invest_storage_all_nonconvex(self): ) ) }, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( nonconvex=True, ep_costs=20, offset=30, @@ -1817,7 +1817,7 @@ def test_nonconvex_invest_sink_without_offset(self): summed_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, minimum=15, nonconvex=True, @@ -1841,7 +1841,7 @@ def test_nonconvex_invest_source_with_offset(self): summed_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, minimum=15, maximum=20, @@ -1866,7 +1866,7 @@ def test_nonconvex_invest_source_with_offset_no_minimum(self): summed_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, maximum=1234, offset=34, @@ -2009,7 +2009,7 @@ def test_multi_period_varying_period_length(self): inputs={ bel: solph.Flow( variable_costs=0, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=10, existing=0, lifetime=20, @@ -2021,7 +2021,7 @@ def test_multi_period_varying_period_length(self): outputs={ bel: solph.Flow( variable_costs=0, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=10, existing=0, lifetime=20, @@ -2036,7 +2036,7 @@ def test_multi_period_varying_period_length(self): # inflow_conversion_factor=1, # outflow_conversion_factor=0.8, # nominal_storage_capacity=100, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=10, maximum=float("+inf"), existing=0, diff --git a/tests/test_components.py b/tests/test_components.py index cde311415..9e71d4b13 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -36,7 +36,7 @@ def test_generic_storage_1(): invest_relation_input_output=1, invest_relation_output_capacity=1, invest_relation_input_capacity=1, - investment=Investment(), + nominal_storage_capacity=Investment(), inflow_conversion_factor=1, outflow_conversion_factor=0.8, ) @@ -112,7 +112,7 @@ def test_generic_storage_with_non_convex_investment(): outputs={bel: Flow()}, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, - investment=Investment(nonconvex=True, existing=5, maximum=25), + nominal_value=Investment(nonconvex=True, existing=5, maximum=25), ) @@ -128,7 +128,7 @@ def test_generic_storage_with_non_convex_invest_maximum(): outputs={bel: Flow()}, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, - investment=Investment(nonconvex=True), + nominal_storage_capacity=Investment(nonconvex=True), ) @@ -144,7 +144,7 @@ def test_generic_storage_with_convex_invest_offset(): outputs={bel: Flow()}, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, - investment=Investment(offset=10), + nominal_storage_capacity=Investment(offset=10), ) @@ -164,13 +164,16 @@ def test_generic_storage_with_invest_and_fixed_losses_absolute(): label="storage4", inputs={bel: Flow()}, outputs={bel: Flow()}, - investment=Investment(ep_costs=23, minimum=0, existing=0), + nominal_storage_capacity=Investment( + ep_costs=23, minimum=0, existing=0 + ), fixed_losses_absolute=[0, 0, 4], ) def test_generic_storage_without_inputs(): - components.GenericStorage(label="storage5") + with pytest.warns(SuspiciousUsageWarning): + components.GenericStorage(label="storage5") def test_generic_storage_too_many_inputs(): @@ -179,7 +182,9 @@ def test_generic_storage_too_many_inputs(): bel2 = Bus() with pytest.raises(AttributeError, match=msg): components.GenericStorage( - label="storage6", inputs={bel1: Flow(), bel2: Flow()} + label="storage6", + inputs={bel1: Flow(), bel2: Flow()}, + outputs={bel2: Flow()}, ) @@ -189,7 +194,9 @@ def test_generic_storage_too_many_outputs(): bel2 = Bus() with pytest.raises(AttributeError, match=msg): components.GenericStorage( - label="storage7", outputs={bel1: Flow(), bel2: Flow()} + label="storage7", + inputs={bel1: Flow()}, + outputs={bel1: Flow(), bel2: Flow()}, ) @@ -234,10 +241,10 @@ def test_offsetconverter_investment_on_inputs(): ): b_diesel = Bus(label="bus_diesel") components.OffsetConverter( - inputs={b_diesel: Flow(investment=Investment())}, + inputs={b_diesel: Flow(nominal_value=Investment())}, outputs={ b_diesel: Flow( - nonconvex=NonConvex(), investment=Investment(maximum=1) + nonconvex=NonConvex(), nominal_value=Investment(maximum=1) ) }, coefficients=(2.5, 0.5), diff --git a/tests/test_constraints_module.py b/tests/test_constraints_module.py index 09f461525..e28889a55 100644 --- a/tests/test_constraints_module.py +++ b/tests/test_constraints_module.py @@ -5,7 +5,10 @@ def test_special(): date_time_index = pd.date_range("1/1/2012", periods=5, freq="H") - energysystem = solph.EnergySystem(timeindex=date_time_index) + energysystem = solph.EnergySystem( + timeindex=date_time_index, + infer_last_interval=True, + ) bel = solph.buses.Bus(label="electricityBus") flow1 = solph.flows.Flow( nominal_value=100, @@ -26,7 +29,9 @@ def test_special(): def test_something_else(): date_time_index = pd.date_range("1/1/2012", periods=5, freq="H") - energysystem = solph.EnergySystem(timeindex=date_time_index) + energysystem = solph.EnergySystem( + timeindex=date_time_index, infer_last_interval=True + ) bel1 = solph.buses.Bus(label="electricity1") bel2 = solph.buses.Bus(label="electricity2") energysystem.add(bel1, bel2) @@ -36,7 +41,7 @@ def test_something_else(): inputs={bel1: solph.flows.Flow()}, outputs={ bel2: solph.flows.Flow( - investment=solph.Investment(ep_costs=20) + nominal_value=solph.Investment(ep_costs=20) ) }, ) @@ -47,7 +52,7 @@ def test_something_else(): inputs={bel2: solph.flows.Flow()}, outputs={ bel1: solph.flows.Flow( - investment=solph.Investment(ep_costs=20) + nominal_value=solph.Investment(ep_costs=20) ) }, ) diff --git a/tests/test_energy_system.py b/tests/test_energy_system.py index 574d5cf9f..7828f31dd 100644 --- a/tests/test_energy_system.py +++ b/tests/test_energy_system.py @@ -19,7 +19,9 @@ def test_add_periods(): pd.date_range(start="2012-01-01", periods=8784, freq="H"), pd.date_range(start="2013-01-01", periods=1217, freq="H"), ] - es = EnergySystem(timeindex=timeindex, periods=periods) + es = EnergySystem( + timeindex=timeindex, periods=periods, infer_last_interval=True + ) assert len(es.periods) == 2 assert es.periods[0].equals( pd.date_range(start="2012-01-01", periods=8784, freq="H") diff --git a/tests/test_grouping.py b/tests/test_grouping.py index 1d4801d3b..c9f0c450d 100644 --- a/tests/test_grouping.py +++ b/tests/test_grouping.py @@ -55,7 +55,7 @@ def test_investment_flow_grouping(self): full_load_time_max=2.3, variable_costs=25, max=0.8, - investment=Investment(ep_costs=500, maximum=10e5), + nominal_value=Investment(ep_costs=500, maximum=10e5), ) }, ) diff --git a/tests/test_models.py b/tests/test_models.py index d42f4252f..4eabbd783 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -72,7 +72,9 @@ def test_multi_period_default_discount_rate(): """Test error being thrown for default multi-period discount rate""" warnings.filterwarnings("ignore", category=FutureWarning) timeindex = pd.date_range(start="2017-01-01", periods=100, freq="D") - es = solph.EnergySystem(timeindex=timeindex, periods={0: timeindex}) + es = solph.EnergySystem( + timeindex=timeindex, periods={0: timeindex}, infer_last_interval=True + ) bel = solph.buses.Bus(label="bus") es.add(bel) es.add( diff --git a/tests/test_non_equidistant_time_index.py b/tests/test_non_equidistant_time_index.py index 60da70a97..d4f3592f3 100644 --- a/tests/test_non_equidistant_time_index.py +++ b/tests/test_non_equidistant_time_index.py @@ -40,7 +40,7 @@ def setup_class(cls): inputs={b_diesel: flows.Flow(variable_costs=2)}, outputs={ b_el1: flows.Flow( - variable_costs=1, investment=Investment(ep_costs=500) + variable_costs=1, nominal_value=Investment(ep_costs=500) ) }, conversion_factors={b_el1: 0.5}, diff --git a/tests/test_options.py b/tests/test_options.py index c209c5e79..a0700c329 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -15,4 +15,6 @@ def test_check_age_and_lifetime(): """Check error being thrown if age > lifetime""" msg = "A unit's age must be smaller than its expected lifetime." with pytest.raises(AttributeError, match=msg): - solph.components.Sink(investment=solph.Investment(age=41, lifetime=40)) + solph.components.Sink( + nominal_value=solph.Investment(age=41, lifetime=40) + ) diff --git a/tests/test_outputlib/__init__.py b/tests/test_outputlib/__init__.py index 78f002380..752119194 100644 --- a/tests/test_outputlib/__init__.py +++ b/tests/test_outputlib/__init__.py @@ -123,7 +123,7 @@ ) datetimeindex = pd.date_range("1/1/2012", periods=24, freq="H") -energysystem = EnergySystem(timeindex=datetimeindex) +energysystem = EnergySystem(timeindex=datetimeindex, infer_last_interval=True) energysystem.add( bcoal, bgas, diff --git a/tests/test_processing.py b/tests/test_processing.py index ae0695ae4..c7d9d5842 100644 --- a/tests/test_processing.py +++ b/tests/test_processing.py @@ -32,8 +32,11 @@ def setup_class(cls): cls.period = 24 cls.es = EnergySystem( timeindex=pandas.date_range( - "2016-01-01", periods=cls.period, freq="H" - ) + "2016-01-01", + periods=cls.period, + freq="H", + ), + infer_last_interval=True, ) # BUSSES @@ -48,7 +51,7 @@ def setup_class(cls): inputs={b_diesel: Flow(variable_costs=2)}, outputs={ b_el1: Flow( - variable_costs=1, investment=Investment(ep_costs=0.5) + variable_costs=1, nominal_value=Investment(ep_costs=0.5) ) }, conversion_factors={b_el1: 2}, @@ -64,7 +67,7 @@ def setup_class(cls): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - investment=Investment(ep_costs=0.4), + nominal_storage_capacity=Investment(ep_costs=0.4), ) cls.demand_values = [0.0] + [100] * 23 diff --git a/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py b/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py index 9bff4ad64..498261204 100644 --- a/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py +++ b/tests/test_scripts/test_solph/test_connect_invest/test_connect_invest.py @@ -30,7 +30,7 @@ def test_connect_invest(): date_time_index = pd.date_range("1/1/2012", periods=24 * 7, freq="H") - es = EnergySystem(timeindex=date_time_index) + es = EnergySystem(timeindex=date_time_index, infer_last_interval=True) # Read data file full_filename = os.path.join( @@ -79,21 +79,21 @@ def test_connect_invest(): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - investment=Investment(ep_costs=0.2), + nominal_storage_capacity=Investment(ep_costs=0.2), ) es.add(storage) line12 = components.Converter( label="line12", inputs={bel1: Flow()}, - outputs={bel2: Flow(investment=Investment(ep_costs=20))}, + outputs={bel2: Flow(nominal_value=Investment(ep_costs=20))}, ) es.add(line12) line21 = components.Converter( label="line21", inputs={bel2: Flow()}, - outputs={bel1: Flow(investment=Investment(ep_costs=20))}, + outputs={bel1: Flow(nominal_value=Investment(ep_costs=20))}, ) es.add(line21) @@ -119,16 +119,18 @@ def test_connect_invest(): results = processing.results(om) my_results = dict() - my_results["line12"] = float( - views.node(results, "line12")["scalars"].loc[ - [(("line12", "electricity2"), "invest")] - ] + my_results["line12"] = ( + views.node(results, "line12")["scalars"] + .loc[[(("line12", "electricity2"), "invest")]] + .iloc[0] ) - my_results["line21"] = float( - views.node(results, "line21")["scalars"].loc[ - [(("line21", "electricity1"), "invest")] - ] + + my_results["line21"] = ( + views.node(results, "line21")["scalars"] + .loc[[(("line21", "electricity1"), "invest")]] + .iloc[0] ) + stor_res = views.node(results, "storage")["scalars"] my_results["storage_in"] = stor_res[ [(("electricity1", "storage"), "invest")] diff --git a/tests/test_scripts/test_solph/test_flexible_modelling/test_add_constraints.py b/tests/test_scripts/test_solph/test_flexible_modelling/test_add_constraints.py index 7dfd74a12..7851f9d52 100644 --- a/tests/test_scripts/test_solph/test_flexible_modelling/test_add_constraints.py +++ b/tests/test_scripts/test_solph/test_flexible_modelling/test_add_constraints.py @@ -31,7 +31,10 @@ def test_add_constraints_example(solver="cbc", nologg=False): logging.basicConfig(level=logging.INFO) # ##### creating an oemof solph optimization model, nothing special here ## # create an energy system object for the oemof solph nodes - es = EnergySystem(timeindex=pd.date_range("1/1/2012", periods=4, freq="H")) + es = EnergySystem( + timeindex=pd.date_range("1/1/2012", periods=4, freq="H"), + infer_last_interval=True, + ) # add some nodes boil = Bus(label="oil", balanced=False) diff --git a/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py b/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py index a4a907ba4..1b2b78590 100644 --- a/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py +++ b/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py @@ -38,7 +38,7 @@ def test_gen_caes(): # create an energy system idx = pd.date_range("1/1/2017", periods=periods, freq="H") - es = EnergySystem(timeindex=idx) + es = EnergySystem(timeindex=idx, infer_last_interval=True) # resources bgas = Bus(label="bgas") diff --git a/tests/test_scripts/test_solph/test_generic_chp/test_generic_chp.py b/tests/test_scripts/test_solph/test_generic_chp/test_generic_chp.py index 54c2744af..910c83532 100644 --- a/tests/test_scripts/test_solph/test_generic_chp/test_generic_chp.py +++ b/tests/test_scripts/test_solph/test_generic_chp/test_generic_chp.py @@ -32,7 +32,7 @@ def test_gen_chp(): # create an energy system idx = pd.date_range("1/1/2017", periods=periods, freq="H") - es = solph.EnergySystem(timeindex=idx) + es = solph.EnergySystem(timeindex=idx, infer_last_interval=True) # resources bgas = solph.buses.Bus(label="bgas") diff --git a/tests/test_scripts/test_solph/test_invest_fix_flow/test_simple_invest_fixed.py b/tests/test_scripts/test_solph/test_invest_fix_flow/test_simple_invest_fixed.py index 3778ed6c3..8f2eb1d71 100644 --- a/tests/test_scripts/test_solph/test_invest_fix_flow/test_simple_invest_fixed.py +++ b/tests/test_scripts/test_solph/test_invest_fix_flow/test_simple_invest_fixed.py @@ -50,7 +50,7 @@ def test_dispatch_fix_example(solver="cbc", periods=10): pv = Source( label="pv", outputs={ - bel: Flow(fix=data["pv"], investment=Investment(ep_costs=ep_pv)) + bel: Flow(fix=data["pv"], nominal_value=Investment(ep_costs=ep_pv)) }, ) @@ -62,7 +62,9 @@ def test_dispatch_fix_example(solver="cbc", periods=10): datetimeindex = pd.date_range("1/1/2012", periods=periods, freq="H") - energysystem = EnergySystem(timeindex=datetimeindex) + energysystem = EnergySystem( + timeindex=datetimeindex, infer_last_interval=True + ) energysystem.add(bel, excess_el, pv, demand_el) diff --git a/tests/test_scripts/test_solph/test_lopf/test_lopf.py b/tests/test_scripts/test_solph/test_lopf/test_lopf.py index beccd909a..740ed47d9 100644 --- a/tests/test_scripts/test_solph/test_lopf/test_lopf.py +++ b/tests/test_scripts/test_solph/test_lopf/test_lopf.py @@ -34,7 +34,7 @@ def test_lopf(solver="cbc"): # create time index for 192 hours in May. date_time_index = pd.date_range("5/5/2012", periods=1, freq="H") - es = EnergySystem(timeindex=date_time_index) + es = EnergySystem(timeindex=date_time_index, infer_last_interval=True) ########################################################################## # Create oemof.solph objects @@ -55,7 +55,7 @@ def test_lopf(solver="cbc"): input=b_el0, output=b_el1, reactance=0.0001, - investment=Investment(ep_costs=10), + nominal_value=Investment(ep_costs=10), min=-1, max=1, ) diff --git a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py index 1c6d4ca63..ccf3e3b91 100644 --- a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py +++ b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py @@ -139,7 +139,7 @@ def test_multi_period_investment_model(solver="cbc"): inputs={bus_lignite: flows.Flow()}, outputs={ bus_el: flows.Flow( - investment=_options.Investment( + nominal_value=_options.Investment( maximum=1000, ep_costs=2e6, existing=0, @@ -158,7 +158,7 @@ def test_multi_period_investment_model(solver="cbc"): inputs={bus_hardcoal: flows.Flow()}, # )}, outputs={ bus_el: flows.Flow( - investment=_options.Investment( + nominal_value=_options.Investment( maximum=1000, ep_costs=1.6e6, existing=0, @@ -177,7 +177,7 @@ def test_multi_period_investment_model(solver="cbc"): inputs={bus_natgas: flows.Flow()}, # )}, outputs={ bus_el: flows.Flow( - investment=_options.Investment( + nominal_value=_options.Investment( maximum=1000, ep_costs=1e6, existing=0, @@ -196,7 +196,7 @@ def test_multi_period_investment_model(solver="cbc"): inputs={bus_natgas: flows.Flow()}, # )}, outputs={ bus_el: flows.Flow( - investment=_options.Investment( + nominal_value=_options.Investment( maximum=1000, ep_costs=[0.6e6, 0.5e6, 0.8e6, 0.4e6], existing=0, @@ -217,7 +217,7 @@ def test_multi_period_investment_model(solver="cbc"): bus_el: flows.Flow( variable_costs=0, max=1, - investment=_options.Investment( + nominal_value=_options.Investment( maximum=20, ep_costs=1000, existing=10, @@ -231,7 +231,7 @@ def test_multi_period_investment_model(solver="cbc"): bus_el: flows.Flow( variable_costs=0, max=1, - investment=_options.Investment( + nominal_value=_options.Investment( maximum=20, ep_costs=1000, existing=10, @@ -251,7 +251,7 @@ def test_multi_period_investment_model(solver="cbc"): invest_relation_input_capacity=None, invest_relation_output_capacity=None, fixed_costs=10, - investment=_options.Investment( + nominal_storage_capacity=_options.Investment( maximum=20, ep_costs=1000, existing=10, diff --git a/tests/test_scripts/test_solph/test_piecewiselineartransformer/test_piecewiselineartransformer.py b/tests/test_scripts/test_solph/test_piecewiselineartransformer/test_piecewiselineartransformer.py index 89942bb6c..19a89ad27 100644 --- a/tests/test_scripts/test_solph/test_piecewiselineartransformer/test_piecewiselineartransformer.py +++ b/tests/test_scripts/test_solph/test_piecewiselineartransformer/test_piecewiselineartransformer.py @@ -31,7 +31,9 @@ def test_pwltf(): demand = np.arange(0, step * periods, step) # Set up EnergySystem, buses and sink - energysystem = EnergySystem(timeindex=datetimeindex) + energysystem = EnergySystem( + timeindex=datetimeindex, infer_last_interval=True + ) b_gas = Bus(label="biogas", balanced=False) b_el = Bus(label="electricity") demand_el = Sink( diff --git a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch.py b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch.py index 44da686c7..d7fc978ec 100644 --- a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch.py +++ b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch.py @@ -126,7 +126,9 @@ def test_dispatch_example(solver="cbc", periods=24 * 5): ) datetimeindex = pd.date_range("1/1/2012", periods=periods, freq="H") - energysystem = EnergySystem(timeindex=datetimeindex) + energysystem = EnergySystem( + timeindex=datetimeindex, infer_last_interval=True + ) energysystem.add( bcoal, bgas, diff --git a/tests/test_scripts/test_solph/test_simple_model/test_simple_invest.py b/tests/test_scripts/test_solph/test_simple_model/test_simple_invest.py index a1d53601a..dcefb11e8 100644 --- a/tests/test_scripts/test_solph/test_simple_model/test_simple_invest.py +++ b/tests/test_scripts/test_solph/test_simple_model/test_simple_invest.py @@ -61,7 +61,7 @@ def test_dispatch_example(solver="cbc", periods=24 * 5): outputs={ bel: Flow( fix=data["wind"], - investment=Investment(ep_costs=ep_wind, existing=100), + nominal_value=Investment(ep_costs=ep_wind, existing=100), ) }, ) @@ -72,7 +72,7 @@ def test_dispatch_example(solver="cbc", periods=24 * 5): outputs={ bel: Flow( fix=data["pv"], - investment=Investment(ep_costs=ep_pv, existing=80), + nominal_value=Investment(ep_costs=ep_pv, existing=80), ) }, ) @@ -142,7 +142,9 @@ def test_dispatch_example(solver="cbc", periods=24 * 5): ) datetimeindex = pd.date_range("1/1/2012", periods=periods, freq="H") - energysystem = EnergySystem(timeindex=datetimeindex) + energysystem = EnergySystem( + timeindex=datetimeindex, infer_last_interval=True + ) energysystem.add( bcoal, bgas, diff --git a/tests/test_scripts/test_solph/test_storage_investment/test_invest_storage_regression.py b/tests/test_scripts/test_solph/test_storage_investment/test_invest_storage_regression.py index 34089738d..1faa13677 100644 --- a/tests/test_scripts/test_solph/test_storage_investment/test_invest_storage_regression.py +++ b/tests/test_scripts/test_solph/test_storage_investment/test_invest_storage_regression.py @@ -68,12 +68,16 @@ def test_regression_investment_storage(solver="cbc"): label="storage", inputs={ bel: solph.flows.Flow( - investment=solph.Investment(existing=625046 / 6, maximum=0) + nominal_value=solph.Investment( + existing=625046 / 6, maximum=0 + ) ) }, outputs={ bel: solph.flows.Flow( - investment=solph.Investment(existing=104174.33, maximum=1) + nominal_value=solph.Investment( + existing=104174.33, maximum=1 + ) ) }, loss_rate=0.00, @@ -82,7 +86,10 @@ def test_regression_investment_storage(solver="cbc"): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - investment=solph.Investment(ep_costs=50, existing=625046), + nominal_storage_capacity=solph.Investment( + ep_costs=50, + existing=625046, + ), ) ) diff --git a/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py b/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py index 0975a8d15..3d89bde91 100644 --- a/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py +++ b/tests/test_scripts/test_solph/test_storage_investment/test_storage_investment.py @@ -56,7 +56,10 @@ def test_optimise_storage_size( logging.info("Initialize the energy system") date_time_index = pd.date_range("1/1/2012", periods=400, freq="H") - es = solph.EnergySystem(timeindex=date_time_index) + es = solph.EnergySystem( + timeindex=date_time_index, + infer_last_interval=True, + ) full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") @@ -136,7 +139,10 @@ def test_optimise_storage_size( invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - investment=solph.Investment(ep_costs=epc, existing=6851), + nominal_storage_capacity=solph.Investment( + ep_costs=epc, + existing=6851, + ), ) ) diff --git a/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py b/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py index 9efa8ed88..998373fac 100644 --- a/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py +++ b/tests/test_scripts/test_solph/test_storage_investment/test_storage_with_tuple_label.py @@ -65,7 +65,10 @@ def test_tuples_as_labels_example( logging.info("Initialize the energy system") date_time_index = pd.date_range("1/1/2012", periods=40, freq="H") - energysystem = solph.EnergySystem(timeindex=date_time_index) + energysystem = solph.EnergySystem( + timeindex=date_time_index, + infer_last_interval=True, + ) full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") diff --git a/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py b/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py index 4af4e53fa..9753e3684 100644 --- a/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py +++ b/tests/test_scripts/test_solph/test_variable_chp/test_variable_chp.py @@ -27,7 +27,9 @@ def test_variable_chp(filename="variable_chp.csv", solver="cbc"): # create time index for 192 hours in May. date_time_index = pd.date_range("5/5/2012", periods=5, freq="H") - energysystem = solph.EnergySystem(timeindex=date_time_index) + energysystem = solph.EnergySystem( + timeindex=date_time_index, infer_last_interval=True + ) # Read data file with heat and electrical demand (192 hours) full_filename = os.path.join(os.path.dirname(__file__), filename) diff --git a/tests/test_time_index.py b/tests/test_time_index.py index 91d5870bf..db4049a1b 100644 --- a/tests/test_time_index.py +++ b/tests/test_time_index.py @@ -17,7 +17,7 @@ def test_energysystem_with_datetimeindex_infer_last_interval(): """Test EnergySystem with DatetimeIndex (equidistant)""" datetimeindex = pd.date_range("1/1/2012", periods=24, freq="H") - es = solph.EnergySystem(timeindex=datetimeindex) + es = solph.EnergySystem(timeindex=datetimeindex, infer_last_interval=True) assert es.timeincrement[1] == 1.0 assert es.timeincrement.sum() == 24 @@ -39,7 +39,7 @@ def test_energysystem_with_datetimeindex_non_equidistant_infer_last_interval(): "DatetimeIndex is None." ) with pytest.raises(AttributeError, match=msg): - solph.EnergySystem(timeindex=dtindex) + solph.EnergySystem(timeindex=dtindex, infer_last_interval=True) def test_energysystem_with_datetimeindex_non_equidistant(): @@ -102,7 +102,7 @@ def test_energysystem_with_numeric_index_non_equidistant(): def test_model_timeincrement_with_valid_timeindex(): datetimeindex = pd.date_range("1/1/2012", periods=5, freq="H") - es = solph.EnergySystem(timeindex=datetimeindex) + es = solph.EnergySystem(timeindex=datetimeindex, infer_last_interval=True) m = solph._models.BaseModel(es) assert es.timeincrement.sum() == 5 assert m.timeincrement.sum() == 5 @@ -125,6 +125,7 @@ def test_conflicting_time_index(): solph.EnergySystem( timeindex=pd.date_range("1/1/2012", periods=2, freq="H"), timeincrement=[1, 2, 3, 4], + infer_last_interval=False, ) @@ -140,7 +141,8 @@ def test_missing_timeincrement(): def test_overwrite_timeincrement(): es = solph.EnergySystem( - timeindex=pd.date_range("1/1/2012", periods=2, freq="H") + timeindex=pd.date_range("1/1/2012", periods=2, freq="H"), + infer_last_interval=True, ) assert es.timeincrement[0] == 1 m = solph._models.BaseModel(es, timeincrement=[3]) diff --git a/tests/test_warnings.py b/tests/test_warnings.py index c3fac5e37..446739277 100644 --- a/tests/test_warnings.py +++ b/tests/test_warnings.py @@ -135,11 +135,10 @@ def test_nonconvex_investment_without_maximum_raises_warning(warning_fixture): with pytest.raises(AttributeError): solph.flows.Flow( - nominal_value=None, variable_costs=25, min=0.2, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, # no maximum is provided here ), nonconvex=solph.NonConvex(), From fc403d358deb6f3ac766c52be869f71a75b4171f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 19:54:57 +0200 Subject: [PATCH 044/180] Fix wrong replacement in TestsConstraint --- tests/constraint_tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/constraint_tests.py b/tests/constraint_tests.py index 71cfbd534..68a714aee 100644 --- a/tests/constraint_tests.py +++ b/tests/constraint_tests.py @@ -367,7 +367,7 @@ def test_storage_invest_4(self): label="storage4", inputs={bel: solph.flows.Flow(nominal_value=80)}, outputs={bel: solph.flows.Flow(nominal_value=100)}, - nominal_value=solph.Investment(ep_costs=145, maximum=500), + nominal_storage_capacity=solph.Investment(ep_costs=145, maximum=500), ) self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_4.lp") @@ -434,7 +434,7 @@ def test_storage_minimum_invest(self): label="storage1", inputs={bel: solph.flows.Flow()}, outputs={bel: solph.flows.Flow()}, - nominal_value=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, minimum=100, maximum=200 ), ) @@ -470,7 +470,7 @@ def test_storage_invest_unbalanced(self): balanced=False, invest_relation_input_capacity=1, invest_relation_output_capacity=1, - nominal_value=solph.Investment(ep_costs=145), + nominal_storage_capacity=solph.Investment(ep_costs=145), ) self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_unbalanced.lp") From 01ebeaafcd19bfc200ec300f2e55166db6def743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:03:25 +0200 Subject: [PATCH 045/180] Fix implicit time step inference --- tests/regression_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression_tests.py b/tests/regression_tests.py index c2409c914..8ec62c759 100644 --- a/tests/regression_tests.py +++ b/tests/regression_tests.py @@ -25,7 +25,7 @@ def test_version_metadata(): def test_wrong_logging_level(): datetimeindex = pd.date_range("1/1/2012", periods=12, freq="H") - es = solph.EnergySystem(timeindex=datetimeindex) + es = solph.EnergySystem(timeindex=datetimeindex, infer_last_interval=True) tools.logger.define_logging() my_logger = logging.getLogger() my_logger.setLevel("DEBUG") From f677ad93a1dbca06904f430b23fabde08db13f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:05:30 +0200 Subject: [PATCH 046/180] Adhere to Black --- tests/constraint_tests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/constraint_tests.py b/tests/constraint_tests.py index 68a714aee..b3a186a36 100644 --- a/tests/constraint_tests.py +++ b/tests/constraint_tests.py @@ -367,7 +367,9 @@ def test_storage_invest_4(self): label="storage4", inputs={bel: solph.flows.Flow(nominal_value=80)}, outputs={bel: solph.flows.Flow(nominal_value=100)}, - nominal_storage_capacity=solph.Investment(ep_costs=145, maximum=500), + nominal_storage_capacity=solph.Investment( + ep_costs=145, maximum=500 + ), ) self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_4.lp") From f9c79ab2a4fc5da70d2816bcac62f8b0f2099cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:07:17 +0200 Subject: [PATCH 047/180] Adhere to Black --- .../diesel_genset_nonconvex_investment.py | 4 +++- .../offset_diesel_genset_nonconvex_investment.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/invest_nonconvex_flow_examples/diesel_genset_nonconvex_investment.py b/examples/invest_nonconvex_flow_examples/diesel_genset_nonconvex_investment.py index d273d3380..8ecaa15af 100644 --- a/examples/invest_nonconvex_flow_examples/diesel_genset_nonconvex_investment.py +++ b/examples/invest_nonconvex_flow_examples/diesel_genset_nonconvex_investment.py @@ -214,7 +214,9 @@ def main(): ), inputs={b_el_dc: solph.flows.Flow(variable_costs=0)}, outputs={ - b_el_dc: solph.flows.Flow(nominal_value=solph.Investment(ep_costs=0)) + b_el_dc: solph.flows.Flow( + nominal_value=solph.Investment(ep_costs=0) + ) }, initial_storage_level=0.0, min_storage_level=0.0, diff --git a/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py b/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py index 15e5164ae..38d2874c3 100644 --- a/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py +++ b/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py @@ -225,7 +225,9 @@ def offset_converter_example(): ), inputs={b_el_dc: solph.flows.Flow(variable_costs=0)}, outputs={ - b_el_dc: solph.flows.Flow(nominal_value=solph.Investment(ep_costs=0)) + b_el_dc: solph.flows.Flow( + nominal_value=solph.Investment(ep_costs=0) + ) }, initial_storage_level=0.0, min_storage_level=0.0, From e54e8b2d6f1ff65439cbe300ffe2fb5076aecee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:17:47 +0200 Subject: [PATCH 048/180] Increment dev release counter --- .bumpversion.cfg | 2 +- VERSION | 2 +- docs/conf.py | 2 +- setup.py | 2 +- src/oemof/solph/__init__.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 8de708172..d2a410849 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.5.2dev0 +current_version = 0.5.2dev1 commit = True tag = True diff --git a/VERSION b/VERSION index 669e6f35c..26d478d27 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -__version__ = "0.5.2dev0" +__version__ = "0.5.2dev1" diff --git a/docs/conf.py b/docs/conf.py index 05665cac1..e94a07367 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,7 @@ def setup(app): year = "2014-2023" author = "oemof-developer-group" copyright = "{0}, {1}".format(year, author) -version = release = "0.5.2dev0" +version = release = "0.5.2dev1" pygments_style = "trac" templates_path = ["."] diff --git a/setup.py b/setup.py index 392b3d1b0..77028a838 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ def read(*names, **kwargs): setup( name="oemof.solph", - version="0.5.2dev0", + version="0.5.2dev1", license="MIT", description=( "A model generator for energy system modelling and optimisation." diff --git a/src/oemof/solph/__init__.py b/src/oemof/solph/__init__.py index 4ea8f8a15..af4cd7eff 100644 --- a/src/oemof/solph/__init__.py +++ b/src/oemof/solph/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.5.2dev0" +__version__ = "0.5.2dev1" from . import buses from . import components From 2129b0a800a7109f052023a7f60e0e516ef05348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:28:40 +0200 Subject: [PATCH 049/180] Delete warning about timeincrement in EnergySystem The ExperimentalFeatureWarning is only issued in multi-period-mode, which is experimental anyway. I don't think we need two warnings. --- src/oemof/solph/_energy_system.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 90125d9ac..871d3bf02 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -130,13 +130,6 @@ def __init__( "conflicting to each other." ) raise AttributeError(msg) - else: - msg = ( - "Ensure that your timeindex and timeincrement are " - "consistent.\nIf you are not considering non-equidistant " - "timeindices, consider only specifying a timeindex." - ) - warnings.warn(msg, debugging.ExperimentalFeatureWarning) elif timeindex is not None and timeincrement is None: df = pd.DataFrame(timeindex) From 240746c5c43f5130c416b4d7aae281d16a06235b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:32:38 +0200 Subject: [PATCH 050/180] Fix include of example_genergic_invest --- examples/generic_invest_limit/example_generic_invest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/generic_invest_limit/example_generic_invest.py b/examples/generic_invest_limit/example_generic_invest.py index 841d49e5a..a428f9c8f 100644 --- a/examples/generic_invest_limit/example_generic_invest.py +++ b/examples/generic_invest_limit/example_generic_invest.py @@ -42,7 +42,7 @@ .. literalinclude:: /../examples/generic_invest_limit/example_generic_invest.py :language: python - :lines: 62-219 + :lines: 62- Installation requirements ------------------------- From 442c3a68423f81c77d6a6ef9a2ae071976ddb9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:39:22 +0200 Subject: [PATCH 051/180] Avoid DataFrame.groupby(*args, axis=1, **kwargs) DataFrame.groupby with axis=1 is deprecated. The message says to do `frame.T.groupby(...)` without axis instead. So did I. --- src/oemof/solph/views.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/oemof/solph/views.py b/src/oemof/solph/views.py index 5719eb583..a97fcdf7d 100644 --- a/src/oemof/solph/views.py +++ b/src/oemof/solph/views.py @@ -406,7 +406,7 @@ def net_storage_flow(results, node_type): dataframes = [] for lb in labels: - subset = df.groupby( + subset = df.T.groupby( lambda x1: ( lambda fr, to, ty: "output" if (fr == lb and ty == "flow") @@ -415,9 +415,8 @@ def net_storage_flow(results, node_type): else "level" if (fr == lb and ty != "flow") else None - )(*x1), - axis=1, - ).sum() + )(*x1) + ).sum().T subset["net_flow"] = subset["output"] - subset["input"] From 1a681f08c9d0c3415b1f8b79f78078637b3850f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:44:17 +0200 Subject: [PATCH 052/180] Ignore ExperimentalFeatureWarning in pytest --- pytest.ini | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 pytest.ini diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..33447956b --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +filterwarnings = + ignore::oemof.tools.debugging.ExperimentalFeatureWarning + From b3ba6f2633da1fb388a6df6300627555d7690e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 12 Oct 2023 20:44:47 +0200 Subject: [PATCH 053/180] Adhere to Black --- src/oemof/solph/views.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/oemof/solph/views.py b/src/oemof/solph/views.py index a97fcdf7d..93a08921e 100644 --- a/src/oemof/solph/views.py +++ b/src/oemof/solph/views.py @@ -406,17 +406,21 @@ def net_storage_flow(results, node_type): dataframes = [] for lb in labels: - subset = df.T.groupby( - lambda x1: ( - lambda fr, to, ty: "output" - if (fr == lb and ty == "flow") - else "input" - if (to == lb and ty == "flow") - else "level" - if (fr == lb and ty != "flow") - else None - )(*x1) - ).sum().T + subset = ( + df.T.groupby( + lambda x1: ( + lambda fr, to, ty: "output" + if (fr == lb and ty == "flow") + else "input" + if (to == lb and ty == "flow") + else "level" + if (fr == lb and ty != "flow") + else None + )(*x1) + ) + .sum() + .T + ) subset["net_flow"] = subset["output"] - subset["input"] From 2d51637b3f9c45eb9a024370d16c82bbd886bc0b Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 09:25:35 +0200 Subject: [PATCH 054/180] Make investment perspectives consistent --- src/oemof/solph/components/_generic_storage.py | 4 ++-- src/oemof/solph/components/experimental/_sink_dsm.py | 6 +++--- src/oemof/solph/flows/_investment_flow_block.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 885ce7d91..0a63157ae 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1758,7 +1758,7 @@ def _objective_expression(self): end_of_optimization - m.es.periods_years[p], lifetime ) present_value_factor = 1 / economics.annuity( - capex=1, n=duration, wacc=m.discount_rate + capex=1, n=duration, wacc=interest ) investment_costs_increment = ( self.invest[n, p] * annuity * present_value_factor @@ -1785,7 +1785,7 @@ def _objective_expression(self): end_of_optimization - m.es.periods_years[p], lifetime ) present_value_factor = 1 / economics.annuity( - capex=1, n=duration, wacc=m.discount_rate + capex=1, n=duration, wacc=interest ) investment_costs_increment = ( self.invest[n, p] * annuity * present_value_factor diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index 5cbddd865..d1655d0e1 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -1371,7 +1371,7 @@ def _objective_expression(self): lifetime, ) present_value_factor = 1 / economics.annuity( - capex=1, n=duration, wacc=m.discount_rate + capex=1, n=duration, wacc=interest ) investment_costs_increment = ( self.invest[g, p] * annuity * present_value_factor @@ -3124,7 +3124,7 @@ def _objective_expression(self): lifetime, ) present_value_factor = 1 / economics.annuity( - capex=1, n=duration, wacc=m.discount_rate + capex=1, n=duration, wacc=interest ) investment_costs_increment = ( self.invest[g, p] * annuity * present_value_factor @@ -5519,7 +5519,7 @@ def _objective_expression(self): lifetime, ) present_value_factor = 1 / economics.annuity( - capex=1, n=duration, wacc=m.discount_rate + capex=1, n=duration, wacc=interest ) investment_costs_increment = ( self.invest[g, p] * annuity * present_value_factor diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index b06ab868e..217a66991 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -907,7 +907,7 @@ def _objective_expression(self): end_of_optimization - m.es.periods_years[p], lifetime ) present_value_factor = 1 / economics.annuity( - capex=1, n=duration, wacc=m.discount_rate + capex=1, n=duration, wacc=interest ) investment_costs_increment = ( self.invest[i, o, p] * annuity * present_value_factor @@ -934,7 +934,7 @@ def _objective_expression(self): end_of_optimization - m.es.periods_years[p], lifetime ) present_value_factor = 1 / economics.annuity( - capex=1, n=duration, wacc=m.discount_rate + capex=1, n=duration, wacc=interest ) investment_costs_increment = ( self.invest[i, o, p] * annuity * present_value_factor From 8c7ac0d7242ab050dfb94a028f512ec26346a05d Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 10:00:09 +0200 Subject: [PATCH 055/180] Refactor and make end_year_of_optimization an attribute of energy system --- src/oemof/solph/_energy_system.py | 35 +++++++++++-------- .../solph/components/_generic_storage.py | 12 +++---- .../components/experimental/_sink_dsm.py | 30 +++++----------- .../solph/flows/_investment_flow_block.py | 16 ++++----- 4 files changed, 41 insertions(+), 52 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 3d40fafe0..8ea67ef42 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -172,8 +172,10 @@ def __init__( ) warnings.warn(msg, debugging.SuspiciousUsageWarning) self.periods = periods - self._extract_periods_years() - self._extract_periods_matrix() + if self.periods is not None: + self._extract_periods_years() + self._extract_periods_matrix() + self._extract_end_year_of_optimization() def _extract_periods_years(self): """Map simulation years to the respective period based on time indices @@ -185,13 +187,12 @@ def _extract_periods_years(self): relative to the start of the optimization run and starting with 0 """ periods_years = [0] - if self.periods is not None: - start_year = self.periods[0].min().year - for k, v in enumerate(self.periods): - if k >= 1: - periods_years.append(v.min().year - start_year) + start_year = self.periods[0].min().year + for k, v in enumerate(self.periods): + if k >= 1: + periods_years.append(v.min().year - start_year) - self.periods_years = periods_years + self.periods_years = periods_years def _extract_periods_matrix(self): """Determines a matrix describing the temporal distance to each period. @@ -205,13 +206,17 @@ def _extract_periods_matrix(self): """ periods_matrix = [] - if self.periods is not None: - period_years = np.array(self.periods_years) - for v in period_years: - row = period_years - v - row = np.where(row < 0, 0, row) - periods_matrix.append(row) - self.periods_matrix = np.array(periods_matrix) + period_years = np.array(self.periods_years) + for v in period_years: + row = period_years - v + row = np.where(row < 0, 0, row) + periods_matrix.append(row) + self.periods_matrix = np.array(periods_matrix) + + def _extract_end_year_of_optimization(self): + """Extract the end of the optimization in years""" + duration_last_period = self.get_period_duration(-1) + self.end_year_of_optimization = self.periods_years[-1] + duration_last_period def get_period_duration(self, period): """Get duration of a period in full years diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 0a63157ae..f36786af8 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1735,10 +1735,6 @@ def _objective_expression(self): "social planner point of view and does not reflect " "microeconomic interest requirements." ) - - duration_last_period = m.es.get_period_duration(-1) - end_of_optimization = m.es.periods_years[-1] + duration_last_period - for n in self.CONVEX_INVESTSTORAGES: lifetime = n.investment.lifetime interest = n.investment.interest_rate @@ -1755,7 +1751,7 @@ def _objective_expression(self): wacc=interest, ) duration = min( - end_of_optimization - m.es.periods_years[p], lifetime + m.es.end_year_of_optimization - m.es.periods_years[p], lifetime ) present_value_factor = 1 / economics.annuity( capex=1, n=duration, wacc=interest @@ -1782,7 +1778,7 @@ def _objective_expression(self): wacc=interest, ) duration = min( - end_of_optimization - m.es.periods_years[p], lifetime + m.es.end_year_of_optimization - m.es.periods_years[p], lifetime ) present_value_factor = 1 / economics.annuity( capex=1, n=duration, wacc=interest @@ -1799,7 +1795,7 @@ def _objective_expression(self): lifetime = n.investment.lifetime for p in m.PERIODS: range_limit = min( - end_of_optimization, + m.es.end_year_of_optimization, m.es.periods_years[p] + lifetime, ) fixed_costs += sum( @@ -1816,7 +1812,7 @@ def _objective_expression(self): if n.investment.fixed_costs[0] is not None: lifetime = n.investment.lifetime age = n.investment.age - range_limit = min(end_of_optimization, lifetime - age) + range_limit = min(m.es.end_year_of_optimization, lifetime - age) fixed_costs += sum( n.investment.existing * n.investment.fixed_costs[pp] diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index d1655d0e1..80a27077c 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -1346,10 +1346,6 @@ def _objective_expression(self): "social planner point of view and does not reflect " "microeconomic interest requirements." ) - - duration_last_period = m.es.get_period_duration(-1) - end_of_optimization = m.es.periods_years[-1] + duration_last_period - for g in self.investdsm: if g.investment.ep_costs is not None: lifetime = g.investment.lifetime @@ -1367,7 +1363,7 @@ def _objective_expression(self): wacc=interest, ) duration = min( - end_of_optimization - m.es.periods_years[p], + m.es.end_year_of_optimization - m.es.periods_years[p], lifetime, ) present_value_factor = 1 / economics.annuity( @@ -1403,7 +1399,7 @@ def _objective_expression(self): lifetime = g.investment.lifetime for p in m.PERIODS: range_limit = min( - end_of_optimization, + m.es.end_year_of_optimization, m.es.periods_years[p] + lifetime, ) fixed_costs += sum( @@ -1420,7 +1416,7 @@ def _objective_expression(self): if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min(end_of_optimization, lifetime - age) + range_limit = min(m.es.end_year_of_optimization, lifetime - age) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] @@ -3099,10 +3095,6 @@ def _objective_expression(self): "social planner point of view and does not reflect " "microeconomic interest requirements." ) - - duration_last_period = m.es.get_period_duration(-1) - end_of_optimization = m.es.periods_years[-1] + duration_last_period - for g in self.investdsm: if g.investment.ep_costs is not None: lifetime = g.investment.lifetime @@ -3120,7 +3112,7 @@ def _objective_expression(self): wacc=interest, ) duration = min( - end_of_optimization - m.es.periods_years[p], + m.es.end_year_of_optimization - m.es.periods_years[p], lifetime, ) present_value_factor = 1 / economics.annuity( @@ -3160,7 +3152,7 @@ def _objective_expression(self): lifetime = g.investment.lifetime for p in m.PERIODS: range_limit = min( - end_of_optimization, + m.es.end_year_of_optimization, m.es.periods_years[p] + lifetime, ) fixed_costs += sum( @@ -3177,7 +3169,7 @@ def _objective_expression(self): if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min(end_of_optimization, lifetime - age) + range_limit = min(m.es.end_year_of_optimization, lifetime - age) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] @@ -5494,10 +5486,6 @@ def _objective_expression(self): "social planner point of view and does not reflect " "microeconomic interest requirements." ) - - duration_last_period = m.es.get_period_duration(-1) - end_of_optimization = m.es.periods_years[-1] + duration_last_period - for g in self.INVESTDR: if g.investment.ep_costs is not None: lifetime = g.investment.lifetime @@ -5515,7 +5503,7 @@ def _objective_expression(self): wacc=interest, ) duration = min( - end_of_optimization - m.es.periods_years[p], + m.es.end_year_of_optimization - m.es.periods_years[p], lifetime, ) present_value_factor = 1 / economics.annuity( @@ -5562,7 +5550,7 @@ def _objective_expression(self): lifetime = g.investment.lifetime for p in m.PERIODS: range_limit = min( - end_of_optimization, + m.es.end_year_of_optimization, m.es.periods_years[p] + lifetime, ) fixed_costs += sum( @@ -5579,7 +5567,7 @@ def _objective_expression(self): if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min(end_of_optimization, lifetime - age) + range_limit = min(m.es.end_year_of_optimization, lifetime - age) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 217a66991..abee72e11 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -884,10 +884,6 @@ def _objective_expression(self): "social planner point of view and does not reflect " "microeconomic interest requirements." ) - - duration_last_period = m.es.get_period_duration(-1) - end_of_optimization = m.es.periods_years[-1] + duration_last_period - for i, o in self.CONVEX_INVESTFLOWS: lifetime = m.flows[i, o].investment.lifetime interest = m.flows[i, o].investment.interest_rate @@ -904,7 +900,8 @@ def _objective_expression(self): wacc=interest, ) duration = min( - end_of_optimization - m.es.periods_years[p], lifetime + m.es.end_year_of_optimization - m.es.periods_years[p], + lifetime, ) present_value_factor = 1 / economics.annuity( capex=1, n=duration, wacc=interest @@ -931,7 +928,8 @@ def _objective_expression(self): wacc=interest, ) duration = min( - end_of_optimization - m.es.periods_years[p], lifetime + m.es.end_year_of_optimization - m.es.periods_years[p], + lifetime, ) present_value_factor = 1 / economics.annuity( capex=1, n=duration, wacc=interest @@ -949,7 +947,7 @@ def _objective_expression(self): lifetime = m.flows[i, o].investment.lifetime for p in m.PERIODS: range_limit = min( - end_of_optimization, + m.es.end_year_of_optimization, m.es.periods_years[p] + lifetime, ) fixed_costs += sum( @@ -966,7 +964,9 @@ def _objective_expression(self): if m.flows[i, o].investment.fixed_costs[0] is not None: lifetime = m.flows[i, o].investment.lifetime age = m.flows[i, o].investment.age - range_limit = min(end_of_optimization, lifetime - age) + range_limit = min( + m.es.end_year_of_optimization, lifetime - age + ) fixed_costs += sum( m.flows[i, o].investment.existing * m.flows[i, o].investment.fixed_costs[pp] From 12d48a08244c1272b90b1868fe4630f28df26448 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 10:00:45 +0200 Subject: [PATCH 056/180] Black it real good --- src/oemof/solph/_energy_system.py | 4 +++- .../solph/components/_generic_storage.py | 10 ++++++--- .../components/experimental/_sink_dsm.py | 21 +++++++++++++------ src/oemof/solph/flows/_simple_flow_block.py | 2 +- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 8ea67ef42..0d84878e6 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -216,7 +216,9 @@ def _extract_periods_matrix(self): def _extract_end_year_of_optimization(self): """Extract the end of the optimization in years""" duration_last_period = self.get_period_duration(-1) - self.end_year_of_optimization = self.periods_years[-1] + duration_last_period + self.end_year_of_optimization = ( + self.periods_years[-1] + duration_last_period + ) def get_period_duration(self, period): """Get duration of a period in full years diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index f36786af8..cd3cc04e7 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1751,7 +1751,8 @@ def _objective_expression(self): wacc=interest, ) duration = min( - m.es.end_year_of_optimization - m.es.periods_years[p], lifetime + m.es.end_year_of_optimization - m.es.periods_years[p], + lifetime, ) present_value_factor = 1 / economics.annuity( capex=1, n=duration, wacc=interest @@ -1778,7 +1779,8 @@ def _objective_expression(self): wacc=interest, ) duration = min( - m.es.end_year_of_optimization - m.es.periods_years[p], lifetime + m.es.end_year_of_optimization - m.es.periods_years[p], + lifetime, ) present_value_factor = 1 / economics.annuity( capex=1, n=duration, wacc=interest @@ -1812,7 +1814,9 @@ def _objective_expression(self): if n.investment.fixed_costs[0] is not None: lifetime = n.investment.lifetime age = n.investment.age - range_limit = min(m.es.end_year_of_optimization, lifetime - age) + range_limit = min( + m.es.end_year_of_optimization, lifetime - age + ) fixed_costs += sum( n.investment.existing * n.investment.fixed_costs[pp] diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index 80a27077c..1f44fc4d2 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -1363,7 +1363,8 @@ def _objective_expression(self): wacc=interest, ) duration = min( - m.es.end_year_of_optimization - m.es.periods_years[p], + m.es.end_year_of_optimization + - m.es.periods_years[p], lifetime, ) present_value_factor = 1 / economics.annuity( @@ -1416,7 +1417,9 @@ def _objective_expression(self): if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min(m.es.end_year_of_optimization, lifetime - age) + range_limit = min( + m.es.end_year_of_optimization, lifetime - age + ) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] @@ -3112,7 +3115,8 @@ def _objective_expression(self): wacc=interest, ) duration = min( - m.es.end_year_of_optimization - m.es.periods_years[p], + m.es.end_year_of_optimization + - m.es.periods_years[p], lifetime, ) present_value_factor = 1 / economics.annuity( @@ -3169,7 +3173,9 @@ def _objective_expression(self): if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min(m.es.end_year_of_optimization, lifetime - age) + range_limit = min( + m.es.end_year_of_optimization, lifetime - age + ) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] @@ -5503,7 +5509,8 @@ def _objective_expression(self): wacc=interest, ) duration = min( - m.es.end_year_of_optimization - m.es.periods_years[p], + m.es.end_year_of_optimization + - m.es.periods_years[p], lifetime, ) present_value_factor = 1 / economics.annuity( @@ -5567,7 +5574,9 @@ def _objective_expression(self): if g.investment.fixed_costs[0] is not None: lifetime = g.investment.lifetime age = g.investment.age - range_limit = min(m.es.end_year_of_optimization, lifetime - age) + range_limit = min( + m.es.end_year_of_optimization, lifetime - age + ) fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] diff --git a/src/oemof/solph/flows/_simple_flow_block.py b/src/oemof/solph/flows/_simple_flow_block.py index 6df02bf70..6866fbd95 100644 --- a/src/oemof/solph/flows/_simple_flow_block.py +++ b/src/oemof/solph/flows/_simple_flow_block.py @@ -417,7 +417,7 @@ def _objective_expression(self): whereby :math:`w(t)` is the objective weighting. - In a multi-period model, in contrast, the following following parts of + In a multi-period model, in contrast, the following parts of the objective function are created: * `Flow.variable_costs` is not `None`: From 5b0a4d7f4ea1ff2531b17cb3507c85700dfb28a8 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 10:04:51 +0200 Subject: [PATCH 057/180] Adjust docs to changes made --- .../solph/components/_generic_storage.py | 10 ++++---- .../components/experimental/_sink_dsm.py | 24 +++++++++---------- .../solph/flows/_investment_flow_block.py | 10 ++++---- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index cd3cc04e7..b0a7808ec 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -893,7 +893,7 @@ class GenericInvestmentStorageBlock(ScalarBlock): .. math:: & E_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) - \cdot \frac {1}{ANF(d, dr)} \cdot DF^{-p}\\ + \cdot \frac {1}{ANF(d, ir)} \cdot DF^{-p}\\ & \forall p \in \textrm{PERIODS} @@ -902,7 +902,7 @@ class GenericInvestmentStorageBlock(ScalarBlock): .. math:: & (E_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) - \cdot \frac {1}{ANF(d, dr)}\\ + \cdot \frac {1}{ANF(d, ir)}\\ & + c_{invest,fix}(p) \cdot b_{invest}(p)) \cdot DF^{-p} \\ & @@ -930,8 +930,8 @@ class GenericInvestmentStorageBlock(ScalarBlock): * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` and interest rate :math:`ir`. - * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` - and discount rate :math:`dr`. + * :math:`ANF(d, ir)` is the annuity factor for duration :math:`d` + and interest rate :math:`ir`. * :math:`d=min\{year_{max} - year(p), l\}` defines the number of years within the optimization horizon that investment annuities are accounted for. @@ -955,7 +955,7 @@ class GenericInvestmentStorageBlock(ScalarBlock): \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ &\\ & - ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} + ANF(d, ir)=\frac {(1+ir)^d \cdot ir} {(1+ir)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The interest rate :math:`i` for the annuity is defined as weighted diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index 1f44fc4d2..7deaf0301 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -781,7 +781,7 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): .. math:: & P_{invest}(p) \cdot A(c_{invest}(p), l, ir) - \cdot \frac {1}{ANF(d, dr)} \cdot DF^{-p} \\ + \cdot \frac {1}{ANF(d, ir)} \cdot DF^{-p} \\ &\\ & \forall p \in \mathbb{P} @@ -814,8 +814,8 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` and interest rate :math:`ir`. - * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` - and discount rate :math:`dr`. + * :math:`ANF(d, ir)` is the annuity factor for duration :math:`d` + and interest rate :math:`ir`. * :math:`d=min\{year_{max} - year(p), l\}` defines the number of years within the optimization horizon that investment annuities are accounted for. @@ -835,7 +835,7 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ &\\ & - ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} + ANF(d, ir)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The interest rate :math:`i` for the annuity is defined as weighted @@ -2205,7 +2205,7 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): .. math:: & P_{invest}(p) \cdot A(c_{invest}(p), l, ir) - \frac {1}{ANF(d, dr)} \cdot DF^{-p} \\ + \frac {1}{ANF(d, ir)} \cdot DF^{-p} \\ &\\ & \quad \quad \quad \quad \forall p \in \mathbb{P} @@ -2236,8 +2236,8 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` and interest rate :math:`ir`. - * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` - and discount rate :math:`dr`. + * :math:`ANF(d, ir)` is the annuity factor for duration :math:`d` + and interest rate :math:`ir`. * :math:`d=min\{year_{max} - year(p), l\}` defines the number of years within the optimization horizon that investment annuities are accounted for. @@ -2257,7 +2257,7 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ &\\ & - ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} + ANF(d, ir)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The interest rate :math:`i` for the annuity is defined as weighted @@ -4372,7 +4372,7 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): .. math:: & P_{invest}(p) \cdot A(c_{invest}(p), l, ir) - \cdot \frac {1}{ANF(d, dr)} \cdot DF^{-p} \\ + \cdot \frac {1}{ANF(d, ir)} \cdot DF^{-p} \\ &\\ & \forall p \in \mathbb{P} @@ -4406,8 +4406,8 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` and interest rate :math:`ir`. - * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` - and discount rate :math:`dr`. + * :math:`ANF(d, ir)` is the annuity factor for duration :math:`d` + and interest rate :math:`ir`. * :math:`d=min\{year_{max} - year(p), l\}` defines the number of years within the optimization horizon that investment annuities are accounted for. @@ -4427,7 +4427,7 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ &\\ & - ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} + ANF(d, ir)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The interest rate :math:`i` for the annuity is defined as weighted diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index abee72e11..f44a0a2fd 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -780,7 +780,7 @@ def _objective_expression(self): .. math:: & P_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) - \cdot \frac {1}{ANF(d, dr)} \cdot DF^{-p}\\ + \cdot \frac {1}{ANF(d, ir)} \cdot DF^{-p}\\ &\\ & \forall p \in \textrm{PERIODS} @@ -790,7 +790,7 @@ def _objective_expression(self): .. math:: & (P_{invest}(p) \cdot A(c_{invest,var}(p), l, ir) - \cdot \frac {1}{ANF(d, dr)}\\ + \cdot \frac {1}{ANF(d, ir)}\\ & + c_{invest,fix}(p) \cdot b_{invest}(p)) \cdot DF^{-p}\\ &\\ @@ -820,8 +820,8 @@ def _objective_expression(self): * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` and interest rate :math:`ir`. - * :math:`ANF(d, dr)` is the annuity factor for duration :math:`d` - and discount rate :math:`dr`. + * :math:`ANF(d, ir)` is the annuity factor for duration :math:`d` + and interest rate :math:`ir`. * :math:`d=min\{year_{max} - year(p), l\}` defines the number of years within the optimization horizon that investment annuities are accounted for. @@ -845,7 +845,7 @@ def _objective_expression(self): \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ &\\ & - ANF(d, dr)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} + ANF(d, ir)=\frac {(1+ir)^d \cdot ir} {(1+ir)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The interest rate :math:`i` for the annuity is defined as weighted From 92a2a1eece5c383eb5f9123468f99231c79e7496 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 10:39:56 +0200 Subject: [PATCH 058/180] Make handling of fixed costs consistent for dispatch-related flows --- .../solph/components/_generic_storage.py | 15 ++++---- .../components/experimental/_sink_dsm.py | 38 +++++++++---------- src/oemof/solph/flows/_simple_flow_block.py | 28 ++++++++------ 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index b0a7808ec..57762af4a 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -599,12 +599,12 @@ def _objective_expression(self): if m.es.periods is not None: for n in self.STORAGES: if n.fixed_costs[0] is not None: - for p in m.PERIODS: - fixed_costs += ( - n.nominal_storage_capacity - * n.fixed_costs[p] - * ((1 + m.discount_rate) ** -p) - ) + fixed_costs += ( + n.nominal_storage_capacity + * n.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range(m.es.end_year_of_optimization) + ) self.fixed_costs = Expression(expr=fixed_costs) storage_costs = 0 @@ -620,8 +620,9 @@ def _objective_expression(self): ) self.storage_costs = Expression(expr=storage_costs) + self.costs = Expression(expr=storage_costs + fixed_costs) - return self.fixed_costs + self.storage_costs + return self.costs class GenericInvestmentStorageBlock(ScalarBlock): diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index 7deaf0301..120e43a15 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -212,7 +212,7 @@ class SinkDSM(Sink): Boolean parameter indicating whether unit is eligible for load shifting fixed_costs : numeric - Nominal value of fixed costs (per period) + Nominal value of fixed costs (per year) Note ---- @@ -695,12 +695,12 @@ def _objective_expression(self): ) if g.fixed_costs[0] is not None: - for p in m.PERIODS: - fixed_costs += ( - max(g.max_capacity_up, g.max_capacity_down) - * g.fixed_costs[p] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) - ) + fixed_costs += ( + max(g.max_capacity_up, g.max_capacity_down) + * g.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range(m.es.end_year_of_optimization) + ) self.variable_costs = Expression(expr=variable_costs) self.fixed_costs = Expression(expr=fixed_costs) @@ -2090,12 +2090,12 @@ def _objective_expression(self): ) if g.fixed_costs[0] is not None: - for p in m.PERIODS: - fixed_costs += ( - max(g.max_capacity_up, g.max_capacity_down) - * g.fixed_costs[p] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) - ) + fixed_costs += ( + max(g.max_capacity_up, g.max_capacity_down) + * g.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range(m.es.end_year_of_optimization) + ) self.variable_costs = Expression(expr=variable_costs) self.fixed_costs = Expression(expr=fixed_costs) @@ -4183,12 +4183,12 @@ def _objective_expression(self): ) if g.fixed_costs[0] is not None: - for p in m.PERIODS: - fixed_costs += ( - max(g.max_capacity_up, g.max_capacity_down) - * g.fixed_costs[p] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) - ) + fixed_costs += ( + max(g.max_capacity_up, g.max_capacity_down) + * g.fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range(m.es.end_year_of_optimization) + ) self.variable_costs = Expression(expr=variable_costs) self.fixed_costs = Expression(expr=fixed_costs) diff --git a/src/oemof/solph/flows/_simple_flow_block.py b/src/oemof/solph/flows/_simple_flow_block.py index 6866fbd95..d20a51814 100644 --- a/src/oemof/solph/flows/_simple_flow_block.py +++ b/src/oemof/solph/flows/_simple_flow_block.py @@ -473,39 +473,45 @@ def _objective_expression(self): * ((1 + m.discount_rate) ** -m.es.periods_years[p]) ) - # Include fixed costs of units operating "forever" + # Fixed costs for units with no lifetime limit if ( m.flows[i, o].fixed_costs[0] is not None and m.flows[i, o].nominal_value is not None and (i, o) not in self.LIFETIME_FLOWS and (i, o) not in self.LIFETIME_AGE_FLOWS ): - for p in m.PERIODS: - fixed_costs += ( - m.flows[i, o].nominal_value - * m.flows[i, o].fixed_costs[p] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) - ) + fixed_costs += ( + m.flows[i, o].nominal_value + * m.flows[i, o].fixed_costs[pp] + * ((1 + m.discount_rate) ** (-pp)) + for pp in range(m.es.end_year_of_optimization) + ) # Fixed costs for units with limited lifetime for i, o in self.LIFETIME_FLOWS: if m.flows[i, o].fixed_costs[0] is not None: + range_limit = min( + m.es.end_year_of_optimization, + m.flows[i, o].lifetime, + ) fixed_costs += sum( m.flows[i, o].nominal_value * m.flows[i, o].fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range(0, m.flows[i, o].lifetime) + for pp in range(range_limit) ) for i, o in self.LIFETIME_AGE_FLOWS: if m.flows[i, o].fixed_costs[0] is not None: + range_limit = min( + m.es.end_year_of_optimization, + m.flows[i, o].lifetime - m.flows[i, o].age, + ) fixed_costs += sum( m.flows[i, o].nominal_value * m.flows[i, o].fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) - for pp in range( - 0, m.flows[i, o].lifetime - m.flows[i, o].age - ) + for pp in range(range_limit) ) self.variable_costs = Expression(expr=variable_costs) From a5892d138e618b8065b4eb2e0e29f48437eb1b70 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 10:47:47 +0200 Subject: [PATCH 059/180] Clarify that fixed costs are accounted for on a yearly basis. --- src/oemof/solph/flows/_flow.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/oemof/solph/flows/_flow.py b/src/oemof/solph/flows/_flow.py index 03b929575..0855ffe86 100644 --- a/src/oemof/solph/flows/_flow.py +++ b/src/oemof/solph/flows/_flow.py @@ -200,13 +200,14 @@ def __init__( if fixed_costs is not None: msg = ( "Be aware that the fixed costs attribute is only\n" - "meant to be used for multi-period models.\n" + "meant to be used for multi-period models to depict " + "fixed costs that occur on a yearly basis.\n" "If you wish to set up a multi-period model, explicitly " "set the `periods` attribute of your energy system.\n" "It has been decided to remove the `fixed_costs` " "attribute with v0.2 for regular uses.\n" "If you specify `fixed_costs` for a regular model, " - "it will simply be ignored." + "this will simply be silently ignored." ) warn(msg, debugging.SuspiciousUsageWarning) From 465ebe469de8f57edf697761120d6cb2beeaf8d1 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 11:22:26 +0200 Subject: [PATCH 060/180] Adjust the docs to code changes and add missing docs --- .../solph/components/_generic_storage.py | 9 ++++--- .../components/experimental/_sink_dsm.py | 26 +++++++++++++++++-- src/oemof/solph/flows/_simple_flow_block.py | 21 ++++++++++----- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 57762af4a..143ca9e78 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -438,11 +438,14 @@ class GenericStorageBlock(ScalarBlock): * :attr:`fixed_costs` not None .. math:: - \sum_{p \in \textrm{PERIODS}} E_{nom} - \cdot c_{fixed}(p) \cdot DF^{-p} + \displaystyle \sum_{pp=0}^{year_{max}} E_{nom} + \cdot c_{fixed}(pp) \cdot DF^{-pp} whereby: - :math:`DF=(1+dr)` is the discount factor with discount rate :math:`dr` + + * :math:`DF=(1+dr)` is the discount factor with discount rate :math:`dr` + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. """ # noqa: E501 diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index 120e43a15..a66b4fa2c 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -446,11 +446,18 @@ class SinkDSMOemofBlock(ScalarBlock): .. math:: & (DSM_{t}^{up} \cdot cost_{t}^{dsm, up} - + DSM_{t}^{do, shift} \cdot cost_{t}^{dsm, do, shift} + + DSM_{t}^{do, shift} \cdot cost_{t}^{dsm, do, shift}\\ + & + DSM_{t}^{do, shed} \cdot cost_{t}^{dsm, do, shed}) \cdot \omega_{t} \\ & \quad \quad \quad \quad \forall t \in \mathbb{T} \\ + * :attr:`fixed_costs` not None + + .. math:: + \displaystyle \sum_{pp=0}^{year_{max}} max\{E_{up, max}, E_{do, max}\} + \cdot c_{fixed}(pp) \cdot DF^{-pp} + **Table: Symbols and attribute names of variables and parameters** .. table:: Variables (V), Parameters (P) and Sets (S) @@ -483,6 +490,7 @@ class SinkDSMOemofBlock(ScalarBlock): :math:`cost_{t}^{dsm, do, shift}` `cost_dsm_down_shift[t]` P Variable costs for a downwards shift (load shifting) :math:`cost_{t}^{dsm, do, shed}` `cost_dsm_down_shift[t]` P Variable costs for shedding load :math:`\omega_{t}` P Objective weighting of the model for timestep t + :math:`year_{max}` P Last year of the optimization horizon ================================= ======================== ==== ======================================= """ # noqa: E501 @@ -1509,12 +1517,18 @@ class SinkDSMDIWBlock(ScalarBlock): .. math:: & DSM_{t}^{up} \cdot cost_{t}^{dsm, up} - + \sum_{tt=0}^{|T|} DSM_{tt, t}^{do, shift} \cdot + + (\sum_{tt=0}^{|T|} DSM_{tt, t}^{do, shift} \cdot cost_{t}^{dsm, do, shift} + DSM_{t}^{do, shed} \cdot cost_{t}^{dsm, do, shed}) \cdot \omega_{t} \\ & \quad \quad \quad \quad \forall t \in \mathbb{T} \\ + * :attr:`fixed_costs` not None + + .. math:: + \displaystyle \sum_{pp=0}^{year_{max}} max\{E_{up, max}, E_{do, max}\} + \cdot c_{fixed}(pp) \cdot DF^{-pp} + **Table: Symbols and attribute names of variables and parameters** .. table:: Variables (V), Parameters (P) and Sets (S) @@ -1557,6 +1571,7 @@ class SinkDSMDIWBlock(ScalarBlock): | and the start of another :math:`\Delta t` P The time increment of the model :math:`\omega_{t}` P Objective weighting of the model for timestep t + :math:`year_{max}` P Last year of the optimization horizon ================================= ======================== ==== ======================================= """ # noqa E:501 @@ -3346,6 +3361,12 @@ class SinkDSMDLRBlock(ScalarBlock): \cdot \omega_{t} \\ & \quad \quad \quad \quad \forall t \in \mathbb{T} \\ + * :attr:`fixed_costs` not None + + .. math:: + \displaystyle \sum_{pp=0}^{year_{max}} max\{E_{up, max}, E_{do, max}\} + \cdot c_{fixed}(pp) \cdot DF^{-pp} + **Table: Symbols and attribute names of variables and parameters** .. table:: Variables (V), Parameters (P) and (additional) Sets (S) @@ -3403,6 +3424,7 @@ class SinkDSMDLRBlock(ScalarBlock): | in the optimization timeframe :math:`t_{dayLimit}` `t_dayLimit` P | Maximum duration of load shifts at full capacity per day | resp. in the last hours before the current" + :math:`year_{max}` P Last year of the optimization horizon =========================================== ================================= ==== ======================================= """ # noqa: E501 diff --git a/src/oemof/solph/flows/_simple_flow_block.py b/src/oemof/solph/flows/_simple_flow_block.py index d20a51814..b72abe114 100644 --- a/src/oemof/solph/flows/_simple_flow_block.py +++ b/src/oemof/solph/flows/_simple_flow_block.py @@ -427,25 +427,32 @@ def _objective_expression(self): * `Flow.fixed_costs` is not `None` and flow has no lifetime limit .. math:: - \sum_{(i,o)} \sum_p P_{nominal} \cdot c_{fixed}(i, o, p) - \cdot DF^{-p} + \sum_{(i,o)} \displaystyle \sum_{pp=0}^{year_{max}} + P_{nominal} \cdot c_{fixed}(i, o, pp) \cdot DF^{-pp} * `Flow.fixed_costs` is not `None` and flow has a lifetime limit, but not an initial age .. math:: - \sum_{(i,o)} \sum_{p}^{p+n} P_{nominal} \cdot c_{fixed}(i, o, p) - \cdot DF^{-p} + \sum_{(i,o)} \displaystyle \sum_{pp=0}^{limit_{exo}} + P_{nominal} \cdot c_{fixed}(i, o, pp) \cdot DF^{-pp} * `Flow.fixed_costs` is not `None` and flow has a lifetime limit, and an initial age .. math:: - \sum_{(i,o)} \sum_{p}^{p+n-a} P_{nominal} - \cdot c_{fixed}(i, o, p) \cdot DF^{-p} + \sum_{(i,o)} \displaystyle \sum_{pp=0}^{limit_{exo}} P_{nominal} + \cdot c_{fixed}(i, o, pp) \cdot DF^{-pp} Hereby + * :math:`DF(p) = (1 + dr)` is the discount factor for period :math:`p` - and :math:`dr` is the discount rate. + and :math:`dr` is the discount rate. * :math:`n` is the unit lifetime and :math:`a` is the initial age. + * :math:`year_{max}` denotes the last year of the optimization + horizon, i.e. at the end of the last period. + * :math:`limit_{exo}=min\{year_{max}, n - a\}` is used as an + upper bound to ensure fixed costs for existing capacities to occur + within the optimization horizon. :math:`a` is the initial age + of an asset (or 0 if not specified). """ m = self.parent_block() From 31c0e92f32c8b92037b5a524b5d5f8654d459424 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 11:27:18 +0200 Subject: [PATCH 061/180] Add bug fix --- src/oemof/solph/components/_generic_storage.py | 2 +- src/oemof/solph/components/experimental/_sink_dsm.py | 6 +++--- src/oemof/solph/flows/_simple_flow_block.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 143ca9e78..802d1703d 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -602,7 +602,7 @@ def _objective_expression(self): if m.es.periods is not None: for n in self.STORAGES: if n.fixed_costs[0] is not None: - fixed_costs += ( + fixed_costs += sum( n.nominal_storage_capacity * n.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index a66b4fa2c..8734f597e 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -703,7 +703,7 @@ def _objective_expression(self): ) if g.fixed_costs[0] is not None: - fixed_costs += ( + fixed_costs += sum( max(g.max_capacity_up, g.max_capacity_down) * g.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) @@ -2105,7 +2105,7 @@ def _objective_expression(self): ) if g.fixed_costs[0] is not None: - fixed_costs += ( + fixed_costs += sum( max(g.max_capacity_up, g.max_capacity_down) * g.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) @@ -4205,7 +4205,7 @@ def _objective_expression(self): ) if g.fixed_costs[0] is not None: - fixed_costs += ( + fixed_costs += sum( max(g.max_capacity_up, g.max_capacity_down) * g.fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) diff --git a/src/oemof/solph/flows/_simple_flow_block.py b/src/oemof/solph/flows/_simple_flow_block.py index b72abe114..32ba487d4 100644 --- a/src/oemof/solph/flows/_simple_flow_block.py +++ b/src/oemof/solph/flows/_simple_flow_block.py @@ -487,7 +487,7 @@ def _objective_expression(self): and (i, o) not in self.LIFETIME_FLOWS and (i, o) not in self.LIFETIME_AGE_FLOWS ): - fixed_costs += ( + fixed_costs += sum( m.flows[i, o].nominal_value * m.flows[i, o].fixed_costs[pp] * ((1 + m.discount_rate) ** (-pp)) From 080536284ee6e9aa1d0e66608fa579f65658c807 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 11:36:35 +0200 Subject: [PATCH 062/180] Update lp files --- tests/lp_files/fixed_costs_sources.lp | 2 +- .../lp_files/storage_invest_1_multi_period.lp | 176 +++++++++--------- 2 files changed, 89 insertions(+), 89 deletions(-) diff --git a/tests/lp_files/fixed_costs_sources.lp b/tests/lp_files/fixed_costs_sources.lp index 7a025ff5e..004e64ad8 100644 --- a/tests/lp_files/fixed_costs_sources.lp +++ b/tests/lp_files/fixed_costs_sources.lp @@ -2,7 +2,7 @@ min objective: -+648.0124531935758 ONE_VAR_CONSTANT ++235.90542099192615 ONE_VAR_CONSTANT +25 flow(pv_forever_electricityBus_0_0) +25 flow(pv_forever_electricityBus_0_1) +24.509803921568626 flow(pv_forever_electricityBus_1_2) diff --git a/tests/lp_files/storage_invest_1_multi_period.lp b/tests/lp_files/storage_invest_1_multi_period.lp index 05d3dcf67..bd64f44ed 100644 --- a/tests/lp_files/storage_invest_1_multi_period.lp +++ b/tests/lp_files/storage_invest_1_multi_period.lp @@ -14,9 +14,9 @@ objective: +23.52941176470588 flow(storage1_electricityBus_1_3) +23.06805074971165 flow(storage1_electricityBus_2_4) +23.06805074971165 flow(storage1_electricityBus_2_5) -+33.55448696821628 GenericInvestmentStorageBlock_invest(storage1_0) -+22.14745251463754 GenericInvestmentStorageBlock_invest(storage1_1) -+10.964085403285921 GenericInvestmentStorageBlock_invest(storage1_2) ++31.685467778602654 GenericInvestmentStorageBlock_invest(storage1_0) ++21.210358847924045 GenericInvestmentStorageBlock_invest(storage1_1) ++10.650825820334894 GenericInvestmentStorageBlock_invest(storage1_2) s.t. @@ -50,25 +50,6 @@ c_e_BusBlock_balance(electricityBus_2_5)_: +1 flow(storage1_electricityBus_2_5) = 0 -c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_0)_: -+1 InvestmentFlowBlock_total(storage1_electricityBus_0) --1 InvestmentFlowBlock_invest(storage1_electricityBus_0) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_1)_: --1 InvestmentFlowBlock_total(storage1_electricityBus_0) -+1 InvestmentFlowBlock_total(storage1_electricityBus_1) --1 InvestmentFlowBlock_invest(storage1_electricityBus_1) -+1 InvestmentFlowBlock_old(storage1_electricityBus_1) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_2)_: --1 InvestmentFlowBlock_total(storage1_electricityBus_1) -+1 InvestmentFlowBlock_total(storage1_electricityBus_2) --1 InvestmentFlowBlock_invest(storage1_electricityBus_2) -+1 InvestmentFlowBlock_old(storage1_electricityBus_2) -= 0 - c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_0)_: +1 InvestmentFlowBlock_total(electricityBus_storage1_0) -1 InvestmentFlowBlock_invest(electricityBus_storage1_0) @@ -88,16 +69,23 @@ c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_2)_: +1 InvestmentFlowBlock_old(electricityBus_storage1_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_0)_: -+1 InvestmentFlowBlock_old_end(storage1_electricityBus_0) +c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_0)_: ++1 InvestmentFlowBlock_total(storage1_electricityBus_0) +-1 InvestmentFlowBlock_invest(storage1_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_1)_: -+1 InvestmentFlowBlock_old_end(storage1_electricityBus_1) +c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_1)_: +-1 InvestmentFlowBlock_total(storage1_electricityBus_0) ++1 InvestmentFlowBlock_total(storage1_electricityBus_1) +-1 InvestmentFlowBlock_invest(storage1_electricityBus_1) ++1 InvestmentFlowBlock_old(storage1_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_2)_: -+1 InvestmentFlowBlock_old_end(storage1_electricityBus_2) +c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_2)_: +-1 InvestmentFlowBlock_total(storage1_electricityBus_1) ++1 InvestmentFlowBlock_total(storage1_electricityBus_2) +-1 InvestmentFlowBlock_invest(storage1_electricityBus_2) ++1 InvestmentFlowBlock_old(storage1_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_0)_: @@ -112,16 +100,16 @@ c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_2)_: +1 InvestmentFlowBlock_old_end(electricityBus_storage1_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_0)_: -+1 InvestmentFlowBlock_old_exo(storage1_electricityBus_0) +c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_0)_: ++1 InvestmentFlowBlock_old_end(storage1_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_1)_: -+1 InvestmentFlowBlock_old_exo(storage1_electricityBus_1) +c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_1)_: ++1 InvestmentFlowBlock_old_end(storage1_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_2)_: -+1 InvestmentFlowBlock_old_exo(storage1_electricityBus_2) +c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_2)_: ++1 InvestmentFlowBlock_old_end(storage1_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_0)_: @@ -136,22 +124,16 @@ c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_2)_: +1 InvestmentFlowBlock_old_exo(electricityBus_storage1_2) = 0 -c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_0)_: --1 InvestmentFlowBlock_old_end(storage1_electricityBus_0) --1 InvestmentFlowBlock_old_exo(storage1_electricityBus_0) -+1 InvestmentFlowBlock_old(storage1_electricityBus_0) +c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_0)_: ++1 InvestmentFlowBlock_old_exo(storage1_electricityBus_0) = 0 -c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_1)_: -+1 InvestmentFlowBlock_old(storage1_electricityBus_1) --1 InvestmentFlowBlock_old_end(storage1_electricityBus_1) --1 InvestmentFlowBlock_old_exo(storage1_electricityBus_1) +c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_1)_: ++1 InvestmentFlowBlock_old_exo(storage1_electricityBus_1) = 0 -c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_2)_: -+1 InvestmentFlowBlock_old(storage1_electricityBus_2) --1 InvestmentFlowBlock_old_end(storage1_electricityBus_2) --1 InvestmentFlowBlock_old_exo(storage1_electricityBus_2) +c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_2)_: ++1 InvestmentFlowBlock_old_exo(storage1_electricityBus_2) = 0 c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_0)_: @@ -172,35 +154,23 @@ c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_2)_: -1 InvestmentFlowBlock_old_exo(electricityBus_storage1_2) = 0 -c_u_InvestmentFlowBlock_max(storage1_electricityBus_0_0)_: -+1 flow(storage1_electricityBus_0_0) --1 InvestmentFlowBlock_total(storage1_electricityBus_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage1_electricityBus_0_1)_: -+1 flow(storage1_electricityBus_0_1) --1 InvestmentFlowBlock_total(storage1_electricityBus_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage1_electricityBus_1_2)_: -+1 flow(storage1_electricityBus_1_2) --1 InvestmentFlowBlock_total(storage1_electricityBus_1) -<= 0 - -c_u_InvestmentFlowBlock_max(storage1_electricityBus_1_3)_: -+1 flow(storage1_electricityBus_1_3) --1 InvestmentFlowBlock_total(storage1_electricityBus_1) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_0)_: +-1 InvestmentFlowBlock_old_end(storage1_electricityBus_0) +-1 InvestmentFlowBlock_old_exo(storage1_electricityBus_0) ++1 InvestmentFlowBlock_old(storage1_electricityBus_0) += 0 -c_u_InvestmentFlowBlock_max(storage1_electricityBus_2_4)_: -+1 flow(storage1_electricityBus_2_4) --1 InvestmentFlowBlock_total(storage1_electricityBus_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_1)_: ++1 InvestmentFlowBlock_old(storage1_electricityBus_1) +-1 InvestmentFlowBlock_old_end(storage1_electricityBus_1) +-1 InvestmentFlowBlock_old_exo(storage1_electricityBus_1) += 0 -c_u_InvestmentFlowBlock_max(storage1_electricityBus_2_5)_: -+1 flow(storage1_electricityBus_2_5) --1 InvestmentFlowBlock_total(storage1_electricityBus_2) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_2)_: ++1 InvestmentFlowBlock_old(storage1_electricityBus_2) +-1 InvestmentFlowBlock_old_end(storage1_electricityBus_2) +-1 InvestmentFlowBlock_old_exo(storage1_electricityBus_2) += 0 c_u_InvestmentFlowBlock_max(electricityBus_storage1_0_0)_: +1 flow(electricityBus_storage1_0_0) @@ -232,6 +202,36 @@ c_u_InvestmentFlowBlock_max(electricityBus_storage1_2_5)_: -1 InvestmentFlowBlock_total(electricityBus_storage1_2) <= 0 +c_u_InvestmentFlowBlock_max(storage1_electricityBus_0_0)_: ++1 flow(storage1_electricityBus_0_0) +-1 InvestmentFlowBlock_total(storage1_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_0_1)_: ++1 flow(storage1_electricityBus_0_1) +-1 InvestmentFlowBlock_total(storage1_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_1_2)_: ++1 flow(storage1_electricityBus_1_2) +-1 InvestmentFlowBlock_total(storage1_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_1_3)_: ++1 flow(storage1_electricityBus_1_3) +-1 InvestmentFlowBlock_total(storage1_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_2_4)_: ++1 flow(storage1_electricityBus_2_4) +-1 InvestmentFlowBlock_total(storage1_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_2_5)_: ++1 flow(storage1_electricityBus_2_5) +-1 InvestmentFlowBlock_total(storage1_electricityBus_2) +<= 0 + c_e_GenericInvestmentStorageBlock_total_storage_rule(storage1_0)_: -1 GenericInvestmentStorageBlock_invest(storage1_0) +1 GenericInvestmentStorageBlock_total(storage1_0) @@ -454,14 +454,6 @@ bounds 0 <= GenericInvestmentStorageBlock_invest(storage1_0) <= 234 0 <= GenericInvestmentStorageBlock_invest(storage1_1) <= 234 0 <= GenericInvestmentStorageBlock_invest(storage1_2) <= 234 - 0 <= InvestmentFlowBlock_total(storage1_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_total(storage1_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old(storage1_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_total(storage1_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_2) <= +inf - 0 <= InvestmentFlowBlock_old(storage1_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_total(electricityBus_storage1_0) <= +inf 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_0) <= +inf 0 <= InvestmentFlowBlock_total(electricityBus_storage1_1) <= +inf @@ -470,20 +462,28 @@ bounds 0 <= InvestmentFlowBlock_total(electricityBus_storage1_2) <= +inf 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_2) <= +inf 0 <= InvestmentFlowBlock_old(electricityBus_storage1_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_total(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_total(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_total(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage1_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_0) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_1) <= +inf 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_2) <= +inf - 0 <= InvestmentFlowBlock_old(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_2) <= +inf 0 <= InvestmentFlowBlock_old(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_old(storage1_electricityBus_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage1_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage1_1) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage1_1) <= +inf From c5240974948ccdc6c45b0bc080c8ca86ad92645d Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 11:39:42 +0200 Subject: [PATCH 063/180] Fix failing tests --- tests/test_models.py | 2 +- tests/test_solph_network_classes.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index d42f4252f..2e53813ed 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -72,7 +72,7 @@ def test_multi_period_default_discount_rate(): """Test error being thrown for default multi-period discount rate""" warnings.filterwarnings("ignore", category=FutureWarning) timeindex = pd.date_range(start="2017-01-01", periods=100, freq="D") - es = solph.EnergySystem(timeindex=timeindex, periods={0: timeindex}) + es = solph.EnergySystem(timeindex=timeindex, periods=[timeindex]) bel = solph.buses.Bus(label="bus") es.add(bel) es.add( diff --git a/tests/test_solph_network_classes.py b/tests/test_solph_network_classes.py index 24c540a62..489dd8c91 100644 --- a/tests/test_solph_network_classes.py +++ b/tests/test_solph_network_classes.py @@ -89,13 +89,14 @@ def test_wrong_combination_invest_and_nominal_value(): def test_fixed_costs_warning(): msg = ( "Be aware that the fixed costs attribute is only\n" - "meant to be used for multi-period models.\n" + "meant to be used for multi-period models to depict " + "fixed costs that occur on a yearly basis.\n" "If you wish to set up a multi-period model, explicitly " "set the `periods` attribute of your energy system.\n" "It has been decided to remove the `fixed_costs` " "attribute with v0.2 for regular uses.\n" "If you specify `fixed_costs` for a regular model, " - "it will simply be ignored." + "this will simply be silently ignored." ) with warnings.catch_warnings(record=True) as w: solph.flows.Flow(fixed_costs=34) From 758be20bd4c6d961b6e79e5a25dffd192d282c14 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 13:25:57 +0200 Subject: [PATCH 064/180] Add missing contributor --- docs/whatsnew/v0-5-2.rst | 1 + src/oemof/solph/components/_generic_storage.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index 4250c29b9..0cdf89701 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -33,3 +33,4 @@ Contributors * Johannes Kochems * Julian Endres * Hendrik Huyskens +* Raul Ciria Aylagas diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 802d1703d..461e03b31 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -15,6 +15,7 @@ SPDX-FileCopyrightText: Ekaterina Zolotarevskaia SPDX-FileCopyrightText: Johannes Kochems SPDX-FileCopyrightText: Johannes Giehl +SPDX-FileCopyrightText: Raul Ciria Aylagas SPDX-License-Identifier: MIT From 2b7ab2c88d93496a2925a0f4852478078228da52 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 13:50:55 +0200 Subject: [PATCH 065/180] Add some minor docs and code formatting fixes --- src/oemof/solph/_energy_system.py | 5 ++- .../solph/components/_generic_storage.py | 8 ++--- .../components/experimental/_sink_dsm.py | 36 +++++++++---------- src/oemof/solph/flows/_flow.py | 3 +- .../solph/flows/_investment_flow_block.py | 4 +-- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 041445d5b..613b7a863 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -209,7 +209,10 @@ def _extract_periods_matrix(self): self.periods_matrix = np.array(periods_matrix) def _extract_end_year_of_optimization(self): - """Extract the end of the optimization in years""" + """Extract the end of the optimization in years + + Attribute `end_year_of_optimization` of int is set. + """ duration_last_period = self.get_period_duration(-1) self.end_year_of_optimization = ( self.periods_years[-1] + duration_last_period diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 461e03b31..098b89c30 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -444,7 +444,7 @@ class GenericStorageBlock(ScalarBlock): whereby: - * :math:`DF=(1+dr)` is the discount factor with discount rate :math:`dr` + * :math:`DF=(1+dr)` is the discount factor with discount rate :math:`dr`. * :math:`year_{max}` denotes the last year of the optimization horizon, i.e. at the end of the last period. @@ -606,7 +606,7 @@ def _objective_expression(self): fixed_costs += sum( n.nominal_storage_capacity * n.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range(m.es.end_year_of_optimization) ) self.fixed_costs = Expression(expr=fixed_costs) @@ -957,13 +957,13 @@ class GenericInvestmentStorageBlock(ScalarBlock): .. math:: & A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot - \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + \frac {(1+ir)^l \cdot ir} {(1+ir)^l - 1}\\ &\\ & ANF(d, ir)=\frac {(1+ir)^d \cdot ir} {(1+ir)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The - interest rate :math:`i` for the annuity is defined as weighted + interest rate :math:`ir` for the annuity is defined as weighted average costs of capital (wacc) and assumed constant over time. The overall summed cost expressions for all *InvestmentFlowBlock* objects diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index 8734f597e..a7e1aa9af 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -691,7 +691,7 @@ def _objective_expression(self): self.dsm_up[g, t] * m.objective_weighting[t] * g.cost_dsm_up[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) variable_costs += ( ( @@ -699,14 +699,14 @@ def _objective_expression(self): + self.dsm_do_shed[g, t] * g.cost_dsm_down_shed[t] ) * m.objective_weighting[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) if g.fixed_costs[0] is not None: fixed_costs += sum( max(g.max_capacity_up, g.max_capacity_down) * g.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range(m.es.end_year_of_optimization) ) @@ -840,13 +840,13 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): .. math:: & A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot - \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + \frac {(1+ir)^l \cdot ir} {(1+ir)^l - 1}\\ &\\ & ANF(d, ir)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The - interest rate :math:`i` for the annuity is defined as weighted + interest rate :math:`ir` for the annuity is defined as weighted average costs of capital (wacc) and assumed constant over time. See remarks in @@ -2089,7 +2089,7 @@ def _objective_expression(self): self.dsm_up[g, t] * m.objective_weighting[t] * g.cost_dsm_up[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) variable_costs += ( ( @@ -2101,14 +2101,14 @@ def _objective_expression(self): + self.dsm_do_shed[g, t] * g.cost_dsm_down_shed[t] ) * m.objective_weighting[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) if g.fixed_costs[0] is not None: fixed_costs += sum( max(g.max_capacity_up, g.max_capacity_down) * g.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range(m.es.end_year_of_optimization) ) @@ -2269,13 +2269,13 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): .. math:: & A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot - \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + \frac {(1+ir)^l \cdot ir} {(1+ir)^l - 1}\\ &\\ & ANF(d, ir)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The - interest rate :math:`i` for the annuity is defined as weighted + interest rate :math:`ir` for the annuity is defined as weighted average costs of capital (wacc) and assumed constant over time. See remarks in @@ -3177,7 +3177,7 @@ def _objective_expression(self): fixed_costs += sum( self.invest[g, p] * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range( m.es.periods_years[p], range_limit, @@ -4188,7 +4188,7 @@ def _objective_expression(self): * g.cost_dsm_up[t] ) * m.objective_weighting[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) variable_costs += ( ( @@ -4201,14 +4201,14 @@ def _objective_expression(self): + self.dsm_do_shed[g, t] * g.cost_dsm_down_shed[t] ) * m.objective_weighting[t] - * ((1 + m.discount_rate) ** -m.es.periods_years[p]) + * (1 + m.discount_rate) ** (-m.es.periods_years[p]) ) if g.fixed_costs[0] is not None: fixed_costs += sum( max(g.max_capacity_up, g.max_capacity_down) * g.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range(m.es.end_year_of_optimization) ) @@ -4446,13 +4446,13 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): .. math:: & A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot - \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + \frac {(1+ir)^l \cdot ir} {(1+ir)^l - 1}\\ &\\ & ANF(d, ir)=\frac {(1+dr)^d \cdot dr} {(1+dr)^d - 1} They are retrieved, using oemof.tools.economics annuity function. The - interest rate :math:`i` for the annuity is defined as weighted + interest rate :math:`ir` for the annuity is defined as weighted average costs of capital (wacc) and assumed constant over time. See remarks in @@ -5585,7 +5585,7 @@ def _objective_expression(self): fixed_costs += sum( self.invest[g, p] * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range( m.es.periods_years[p], range_limit, @@ -5602,7 +5602,7 @@ def _objective_expression(self): fixed_costs += sum( g.investment.existing * g.investment.fixed_costs[pp] - * ((1 + m.discount_rate) ** (-pp)) + * (1 + m.discount_rate) ** (-pp) for pp in range(range_limit) ) diff --git a/src/oemof/solph/flows/_flow.py b/src/oemof/solph/flows/_flow.py index 0855ffe86..9ff497782 100644 --- a/src/oemof/solph/flows/_flow.py +++ b/src/oemof/solph/flows/_flow.py @@ -86,7 +86,8 @@ class Flow(on.Edge): :class:`~oemof.solph.flows._simple_flow_block.SimpleFlowBlock`. fixed_costs : numeric (iterable or scalar), :math:`c_{fixed}` The fixed costs associated with a flow. - Note: These are only applicable for a multi-period model. + Note: These are only applicable for a multi-period model + and given on a yearly basis. lifetime : int, :math:`l` The lifetime of a flow (usually given in years); once it reaches its lifetime (considering also diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index e08302f2f..4c82f1975 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -842,13 +842,13 @@ def _objective_expression(self): .. math:: & A(c_{invest,var}(p), l, ir) = c_{invest,var}(p) \cdot - \frac {(1+i)^l \cdot i} {(1+i)^l - 1}\\ + \frac {(1+ir)^l \cdot ir} {(1+ir)^l - 1}\\ &\\ & ANF(d, ir)=\frac {(1+ir)^d \cdot ir} {(1+ir)^d - 1} They are retrieved, using oemof.tools.economics annuity function. - The interest rate :math:`i` for the annuity is defined as weighted + The interest rate :math:`ir` for the annuity is defined as weighted average costs of capital (wacc) and assumed constant over time. """ if not hasattr(self, "INVESTFLOWS"): From 8ef4c4c527a7439563619eb75777f2ac9c0bb4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Fri, 13 Oct 2023 14:00:00 +0200 Subject: [PATCH 066/180] Include pytest.ini in MANIFEST --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index c80f59439..a6ae4d0f5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -17,6 +17,7 @@ include *.md include VERSION include tox.ini +include pytest.ini include *.yml include *.yaml From 27d677da76ad20cd16b269832641268a484976d9 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 14:03:58 +0200 Subject: [PATCH 067/180] Remove obsolete fixed costs parameter --- src/oemof/solph/components/experimental/_generic_caes.py | 2 +- .../test_solph/test_generic_caes/test_generic_caes.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/oemof/solph/components/experimental/_generic_caes.py b/src/oemof/solph/components/experimental/_generic_caes.py index 25948b5bc..562a65e50 100644 --- a/src/oemof/solph/components/experimental/_generic_caes.py +++ b/src/oemof/solph/components/experimental/_generic_caes.py @@ -92,7 +92,7 @@ class GenericCAES(on.Transformer): ... electrical_input={bel: solph.flows.Flow()}, ... fuel_input={bgas: solph.flows.Flow()}, ... electrical_output={bel: solph.flows.Flow()}, - ... params=concept, fixed_costs=0) + ... params=concept) >>> type(caes) """ diff --git a/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py b/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py index 281637777..9c1a0ecc0 100644 --- a/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py +++ b/tests/test_scripts/test_solph/test_generic_caes/test_generic_caes.py @@ -97,7 +97,6 @@ def test_gen_caes(): fuel_input={bgas: Flow()}, electrical_output={bel_sink: Flow()}, params=concept, - fixed_costs=0, ) ) From cfc69664a0637429c1b9c3aad3fc0f1c00be6f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Fri, 13 Oct 2023 14:37:21 +0200 Subject: [PATCH 068/180] Revert "Ignore ExperimentalFeatureWarning in pytest" This reverts commit 1a681f08c9d0c3415b1f8b79f78078637b3850f3. --- pytest.ini | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 pytest.ini diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 33447956b..000000000 --- a/pytest.ini +++ /dev/null @@ -1,4 +0,0 @@ -[pytest] -filterwarnings = - ignore::oemof.tools.debugging.ExperimentalFeatureWarning - From 99385e6ae20396d262746d75d0615246fed0ee5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Fri, 13 Oct 2023 14:37:28 +0200 Subject: [PATCH 069/180] Revert "Include pytest.ini in MANIFEST" This reverts commit 8ef4c4c527a7439563619eb75777f2ac9c0bb4c1. --- MANIFEST.in | 1 - 1 file changed, 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index a6ae4d0f5..c80f59439 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -17,7 +17,6 @@ include *.md include VERSION include tox.ini -include pytest.ini include *.yml include *.yaml From 71c7830606c0b1fa96d87f5d5f7b0e8fcb820580 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 15:09:35 +0200 Subject: [PATCH 070/180] Remove second point --- docs/usage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.rst b/docs/usage.rst index 45a649632..eb31df822 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -61,7 +61,7 @@ The model time is defined by the number of intervals and the length of intervals The index will also be used for the results. For a numeric index the resulting time series will indexed with a numeric index starting with 0. One can use the function -:py:func:`create_time_index` to create an equidistant datetime index. By default the function creates an hourly index for one year, so online the year has to be passed to the function. But it is also possible to change the length of the interval to quarter hours etc.. The default number of intervals is the number needed to cover the given year but the value can be overwritten by the user. +:py:func:`create_time_index` to create an equidistant datetime index. By default the function creates an hourly index for one year, so online the year has to be passed to the function. But it is also possible to change the length of the interval to quarter hours etc. The default number of intervals is the number needed to cover the given year but the value can be overwritten by the user. It is also possible to define the datetime index using pandas. See `pandas date_range guide `_ for more information. From 42e52c95aab084cad24d534c908e676d460c77c0 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Sat, 7 Oct 2023 11:01:46 +0200 Subject: [PATCH 071/180] Implement remaining value in investment flow --- .../solph/flows/_investment_flow_block.py | 150 +++++++++++++++++- 1 file changed, 144 insertions(+), 6 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 4c82f1975..d363e79c2 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -785,6 +785,20 @@ def _objective_expression(self): & \forall p \in \textrm{PERIODS} + In case, the remaining lifetime of an asset is greater than 0, + the difference in value for the investment period compared to the + last period of the optimization horizon is accounted for + as an adder to the investment costs: + + .. math:: + & + P_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - + A(c_{invest,var}(|P|), l_{r}, ir)\\ + & \cdot \frac {1}{ANF(l_{r}, dr)} \cdot DF^{-|P|}\\ + &\\ + & + \forall p \in \textrm{PERIODS} + * :attr:`nonconvex = True` .. math:: @@ -797,6 +811,23 @@ def _objective_expression(self): & \forall p \in \textrm{PERIODS} + In case, the remaining lifetime of an asset is greater than 0, + the difference in value for the investment period compared to the + last period of the optimization horizon is accounted for + as an adder to the investment costs: + + .. math:: + & + (P_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - + A(c_{invest,var}(|P|), l_{r}, ir)\\ + & \cdot \frac {1}{ANF(l_{r}, dr)} \cdot DF^{-|P|}\\ + & + + (c_{invest,fix}(p) - c_{invest,fix}(|P|)) + \cdot b_{invest}(p)) \cdot DF^{-p}\\ + &\\ + & + \forall p \in \textrm{PERIODS} + * :attr:`fixed_costs` not None for investments .. math:: @@ -820,6 +851,9 @@ def _objective_expression(self): * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` and interest rate :math:`ir`. + * :math:`l_{r}` is the remaining lifetime at the end of the optimization + horizon (in case it is greater than 0 and smaller than the actual + lifetime). * :math:`ANF(d, ir)` is the annuity factor for duration :math:`d` and interest rate :math:`ir`. * :math:`d=min\{year_{max} - year(p), l\}` defines the @@ -903,13 +937,22 @@ def _objective_expression(self): m.es.end_year_of_optimization - m.es.periods_years[p], lifetime, ) - present_value_factor = 1 / economics.annuity( + present_value_factor_remaining = 1 / economics.annuity( capex=1, n=duration, wacc=interest ) investment_costs_increment = ( - self.invest[i, o, p] * annuity * present_value_factor + self.invest[i, o, p] + * annuity + * present_value_factor_remaining ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) - investment_costs += investment_costs_increment + remaining_value_difference = ( + self._evaluate_remaining_value_difference( + m, p, i, o, end_of_optimization, lifetime, interest + ) + ) + investment_costs += ( + investment_costs_increment + remaining_value_difference + ) period_investment_costs[p] += investment_costs_increment for i, o in self.NON_CONVEX_INVESTFLOWS: @@ -931,15 +974,31 @@ def _objective_expression(self): m.es.end_year_of_optimization - m.es.periods_years[p], lifetime, ) - present_value_factor = 1 / economics.annuity( + present_value_factor_remaining = 1 / economics.annuity( capex=1, n=duration, wacc=interest ) investment_costs_increment = ( - self.invest[i, o, p] * annuity * present_value_factor + self.invest[i, o, p] + * annuity + * present_value_factor_remaining + self.invest_status[i, o, p] * m.flows[i, o].investment.offset[p] ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) - investment_costs += investment_costs_increment + remaining_value_difference = ( + self._evaluate_remaining_value_difference( + m, + p, + i, + o, + end_of_optimization, + lifetime, + interest, + nonconvex=True, + ) + ) + investment_costs += ( + investment_costs_increment + remaining_value_difference + ) period_investment_costs[p] += investment_costs_increment for i, o in self.INVESTFLOWS: @@ -981,6 +1040,85 @@ def _objective_expression(self): return self.costs + def _evaluate_remaining_value_difference( + self, + m, + p, + i, + o, + end_of_optimization, + lifetime, + interest, + nonconvex=False, + ): + """Evaluate and return the remaining value difference of an investment + + The remaining value difference in the net present values if the asset + was to be liquidated at the end of the optimization horizon and the + net present value using the original investment expenses. + + Parameters + ---------- + m : oemof.solph.models.Model + Optimization model + + p : int + Period in which investment occurs + + # How to reference any type of module? + i : oemof.solph.components.__all__ + start node of flow + + o : oemof.solph.components.__all__ + end node of flow + + end_of_optimization : int + Last year of the optimization horizon + + lifetime : int + lifetime of investment considered + + interest : float + Demanded interest rate for investment + + nonconvex : bool + Indicating whether considered flow is nonconvex. + """ + if end_of_optimization - m.es.periods_years[p] < lifetime: + remaining_lifetime = end_of_optimization - m.es.periods_years[p] + remaining_annuity = economics.annuity( + capex=m.flows[i, o].investment.ep_costs[-1], + n=remaining_lifetime, + wacc=interest, + ) + original_annuity = economics.annuity( + capex=m.flows[i, o].investment.ep_costs[p], + n=remaining_lifetime, + wacc=interest, + ) + present_value_factor_remaining = 1 / economics.annuity( + capex=1, n=remaining_lifetime, wacc=m.discount_rate + ) + if nonconvex: + return ( + self.invest[i, o, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + + self.invest_status[i, o, p] + * ( + m.flows[i, o].investment.offset[-1] + - m.flows[i, o].investment.offset[p] + ) + ) * (1 + m.discount_rate) ** (-end_of_optimization) + else: + return ( + self.invest[i, o, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + ) * (1 + m.discount_rate) ** (-end_of_optimization) + else: + return 0 + def _minimum_investment_constraint(self): """Constraint factory for a minimum investment""" m = self.parent_block() From 42967e7ce02d6939c4f4f388ccad6fa1b4f43177 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 16:34:08 +0200 Subject: [PATCH 072/180] Define attribute use_remaining_value --- src/oemof/solph/_energy_system.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 613b7a863..cf6bce6f6 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -62,6 +62,10 @@ class EnergySystem(es.EnergySystem): For a standard model, periods are not (to be) declared, i.e. None. A list with one entry is derived, i.e. [0]. + use_remaining_value : bool + If True, compare the remaining value of an investment to the + original value (only applicable for multi-period models) + kwargs """ @@ -71,6 +75,7 @@ def __init__( timeincrement=None, infer_last_interval=None, periods=None, + use_remaining_value=False, **kwargs, ): # Doing imports at runtime is generally frowned upon, but should work @@ -160,7 +165,8 @@ def __init__( timeindex=timeindex, timeincrement=timeincrement, **kwargs ) - if periods is not None: + self.periods = periods + if self.periods is not None: msg = ( "CAUTION! You specified the 'periods' attribute for your " "energy system.\n This will lead to creating " @@ -171,11 +177,10 @@ def __init__( "please report them." ) warnings.warn(msg, debugging.SuspiciousUsageWarning) - self.periods = periods - if self.periods is not None: self._extract_periods_years() self._extract_periods_matrix() self._extract_end_year_of_optimization() + self.use_remaining_value = use_remaining_value def _extract_periods_years(self): """Map years in optimization to respective period based on time indices From ebd183a60fee3d8a605bbeef3ab782c9285d4659 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 16:36:22 +0200 Subject: [PATCH 073/180] Update implementation for investment flow block --- .../solph/flows/_investment_flow_block.py | 102 ++++++++++-------- 1 file changed, 57 insertions(+), 45 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index d363e79c2..514a7343f 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -785,7 +785,8 @@ def _objective_expression(self): & \forall p \in \textrm{PERIODS} - In case, the remaining lifetime of an asset is greater than 0, + In case, the remaining lifetime of an asset is greater than 0 and + attribute `use_remaining_value` of the energy system is True, the difference in value for the investment period compared to the last period of the optimization horizon is accounted for as an adder to the investment costs: @@ -794,7 +795,7 @@ def _objective_expression(self): & P_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - A(c_{invest,var}(|P|), l_{r}, ir)\\ - & \cdot \frac {1}{ANF(l_{r}, dr)} \cdot DF^{-|P|}\\ + & \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\ &\\ & \forall p \in \textrm{PERIODS} @@ -811,7 +812,8 @@ def _objective_expression(self): & \forall p \in \textrm{PERIODS} - In case, the remaining lifetime of an asset is greater than 0, + In case, the remaining lifetime of an asset is greater than 0 and + attribute `use_remaining_value` of the energy system is True, the difference in value for the investment period compared to the last period of the optimization horizon is accounted for as an adder to the investment costs: @@ -820,7 +822,7 @@ def _objective_expression(self): & (P_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - A(c_{invest,var}(|P|), l_{r}, ir)\\ - & \cdot \frac {1}{ANF(l_{r}, dr)} \cdot DF^{-|P|}\\ + & \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\ & + (c_{invest,fix}(p) - c_{invest,fix}(|P|)) \cdot b_{invest}(p)) \cdot DF^{-p}\\ @@ -851,9 +853,9 @@ def _objective_expression(self): * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` and interest rate :math:`ir`. - * :math:`l_{r}` is the remaining lifetime at the end of the optimization - horizon (in case it is greater than 0 and smaller than the actual - lifetime). + * :math:`l_{r}` is the remaining lifetime at the end of the + optimization horizon (in case it is greater than 0 and + smaller than the actual lifetime). * :math:`ANF(d, ir)` is the annuity factor for duration :math:`d` and interest rate :math:`ir`. * :math:`d=min\{year_{max} - year(p), l\}` defines the @@ -947,7 +949,13 @@ def _objective_expression(self): ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) remaining_value_difference = ( self._evaluate_remaining_value_difference( - m, p, i, o, end_of_optimization, lifetime, interest + m, + p, + i, + o, + m.es.end_year_of_optimization, + lifetime, + interest, ) ) investment_costs += ( @@ -990,7 +998,7 @@ def _objective_expression(self): p, i, o, - end_of_optimization, + m.es.end_year_of_optimization, lifetime, interest, nonconvex=True, @@ -1046,7 +1054,7 @@ def _evaluate_remaining_value_difference( p, i, o, - end_of_optimization, + end_year_of_optimization, lifetime, interest, nonconvex=False, @@ -1065,14 +1073,13 @@ def _evaluate_remaining_value_difference( p : int Period in which investment occurs - # How to reference any type of module? - i : oemof.solph.components.__all__ + i : any instance of oemof.solph.components start node of flow - o : oemof.solph.components.__all__ + o : any instance of oemof.solph.components end node of flow - end_of_optimization : int + end_year_of_optimization : int Last year of the optimization horizon lifetime : int @@ -1084,38 +1091,43 @@ def _evaluate_remaining_value_difference( nonconvex : bool Indicating whether considered flow is nonconvex. """ - if end_of_optimization - m.es.periods_years[p] < lifetime: - remaining_lifetime = end_of_optimization - m.es.periods_years[p] - remaining_annuity = economics.annuity( - capex=m.flows[i, o].investment.ep_costs[-1], - n=remaining_lifetime, - wacc=interest, - ) - original_annuity = economics.annuity( - capex=m.flows[i, o].investment.ep_costs[p], - n=remaining_lifetime, - wacc=interest, - ) - present_value_factor_remaining = 1 / economics.annuity( - capex=1, n=remaining_lifetime, wacc=m.discount_rate - ) - if nonconvex: - return ( - self.invest[i, o, p] - * (remaining_annuity - original_annuity) - * present_value_factor_remaining - + self.invest_status[i, o, p] - * ( - m.flows[i, o].investment.offset[-1] - - m.flows[i, o].investment.offset[p] - ) - ) * (1 + m.discount_rate) ** (-end_of_optimization) + if m.es.use_remaining_value: + if end_year_of_optimization - m.es.periods_years[p] < lifetime: + remaining_lifetime = lifetime - ( + end_year_of_optimization - m.es.periods_years[p] + ) + remaining_annuity = economics.annuity( + capex=m.flows[i, o].investment.ep_costs[-1], + n=remaining_lifetime, + wacc=interest, + ) + original_annuity = economics.annuity( + capex=m.flows[i, o].investment.ep_costs[p], + n=remaining_lifetime, + wacc=interest, + ) + present_value_factor_remaining = 1 / economics.annuity( + capex=1, n=remaining_lifetime, wacc=interest + ) + if nonconvex: + return ( + self.invest[i, o, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + + self.invest_status[i, o, p] + * ( + m.flows[i, o].investment.offset[-1] + - m.flows[i, o].investment.offset[p] + ) + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + else: + return ( + self.invest[i, o, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) else: - return ( - self.invest[i, o, p] - * (remaining_annuity - original_annuity) - * present_value_factor_remaining - ) * (1 + m.discount_rate) ** (-end_of_optimization) + return 0 else: return 0 From 15b721a985d9e639c0813aa4493792559b22efc0 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 16:38:15 +0200 Subject: [PATCH 074/180] Include remaining value for storage and DSM accordingly --- .../solph/components/_generic_storage.py | 142 ++++++++- .../components/experimental/_sink_dsm.py | 279 +++++++++++++++++- 2 files changed, 415 insertions(+), 6 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 098b89c30..fdb7a1e24 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -902,6 +902,21 @@ class GenericInvestmentStorageBlock(ScalarBlock): & \forall p \in \textrm{PERIODS} + In case, the remaining lifetime of a storage is greater than 0 and + attribute `use_remaining_value` of the energy system is True, + the difference in value for the investment period compared to the + last period of the optimization horizon is accounted for + as an adder to the investment costs: + + .. math:: + & + E_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - + A(c_{invest,var}(|P|), l_{r}, ir)\\ + & \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\ + &\\ + & + \forall p \in \textrm{PERIODS} + * :attr:`nonconvex = True` .. math:: @@ -913,6 +928,24 @@ class GenericInvestmentStorageBlock(ScalarBlock): & \forall p \in \textrm{PERIODS} + In case, the remaining lifetime of a storage is greater than 0 and + attribute `use_remaining_value` of the energy system is True, + the difference in value for the investment period compared to the + last period of the optimization horizon is accounted for + as an adder to the investment costs: + + .. math:: + & + (E_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - + A(c_{invest,var}(|P|), l_{r}, ir)\\ + & \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\ + & + + (c_{invest,fix}(p) - c_{invest,fix}(|P|)) + \cdot b_{invest}(p)) \cdot DF^{-p}\\ + &\\ + & + \forall p \in \textrm{PERIODS} + * :attr:`fixed_costs` not None for investments .. math:: @@ -929,12 +962,14 @@ class GenericInvestmentStorageBlock(ScalarBlock): \sum_{pp=0}^{limit_{exo}} E_{exist} \cdot c_{fixed}(pp) \cdot DF^{-pp} - whereby: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` and interest rate :math:`ir`. + * :math:`l_{r}` is the remaining lifetime at the end of the + optimization horizon (in case it is greater than 0 and + smaller than the actual lifetime). * :math:`ANF(d, ir)` is the annuity factor for duration :math:`d` and interest rate :math:`ir`. * :math:`d=min\{year_{max} - year(p), l\}` defines the @@ -1765,7 +1800,19 @@ def _objective_expression(self): investment_costs_increment = ( self.invest[n, p] * annuity * present_value_factor ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) - investment_costs += investment_costs_increment + remaining_value_difference = ( + self._evaluate_remaining_value_difference( + m, + p, + n, + m.es.end_year_of_optimization, + lifetime, + interest, + ) + ) + investment_costs += ( + investment_costs_increment + remaining_value_difference + ) period_investment_costs[p] += investment_costs_increment for n in self.NON_CONVEX_INVESTSTORAGES: @@ -1794,7 +1841,20 @@ def _objective_expression(self): self.invest[n, p] * annuity * present_value_factor + self.invest_status[n, p] * n.investment.offset[p] ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) - investment_costs += investment_costs_increment + remaining_value_difference = ( + self._evaluate_remaining_value_difference( + m, + p, + n, + m.es.end_year_of_optimization, + lifetime, + interest, + nonconvex=True, + ) + ) + investment_costs += ( + investment_costs_increment + remaining_value_difference + ) period_investment_costs[p] += investment_costs_increment for n in self.INVESTSTORAGES: @@ -1835,3 +1895,79 @@ def _objective_expression(self): self.costs = Expression(expr=investment_costs + fixed_costs) return self.costs + + def _evaluate_remaining_value_difference( + self, + m, + p, + n, + end_year_of_optimization, + lifetime, + interest, + nonconvex=False, + ): + """Evaluate and return the remaining value difference of an investment + + The remaining value difference in the net present values if the asset + was to be liquidated at the end of the optimization horizon and the + net present value using the original investment expenses. + + Parameters + ---------- + m : oemof.solph.models.Model + Optimization model + + p : int + Period in which investment occurs + + n : oemof.solph.components.GenericStorage + storage unit + + end_year_of_optimization : int + Last year of the optimization horizon + + lifetime : int + lifetime of investment considered + + interest : float + Demanded interest rate for investment + + nonconvex : bool + Indicating whether considered flow is nonconvex. + """ + if m.es.use_remaining_value: + if end_year_of_optimization - m.es.periods_years[p] < lifetime: + remaining_lifetime = lifetime - ( + end_year_of_optimization - m.es.periods_years[p] + ) + remaining_annuity = economics.annuity( + capex=n.investment.ep_costs[-1], + n=remaining_lifetime, + wacc=interest, + ) + original_annuity = economics.annuity( + capex=n.investment.ep_costs[p], + n=remaining_lifetime, + wacc=interest, + ) + present_value_factor_remaining = 1 / economics.annuity( + capex=1, n=remaining_lifetime, wacc=interest + ) + if nonconvex: + return ( + self.invest[n, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + + self.invest_status[n, p] + * (n.investment.offset[-1] - n.investment.offset[p]) + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + else: + return ( + self.invest[n, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + else: + return 0 + else: + return 0 diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index a7e1aa9af..88c0335c7 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -794,6 +794,21 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): & \forall p \in \mathbb{P} + In case, the remaining lifetime of a DSM unit is greater than 0 and + attribute `use_remaining_value` of the energy system is True, + the difference in value for the investment period compared to the + last period of the optimization horizon is accounted for + as an adder to the investment costs: + + .. math:: + & + P_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - + A(c_{invest,var}(|P|), l_{r}, ir)\\ + & \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\ + &\\ + & + \forall p \in \textrm{PERIODS} + * :attr:`fixed_costs` not None for investments .. math:: @@ -1381,7 +1396,20 @@ def _objective_expression(self): investment_costs_increment = ( self.invest[g, p] * annuity * present_value_factor ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) - investment_costs += investment_costs_increment + remaining_value_difference = ( + self._evaluate_remaining_value_difference( + m, + p, + g, + m.es.end_year_of_optimization, + lifetime, + interest, + ) + ) + investment_costs += ( + investment_costs_increment + + remaining_value_difference + ) period_investment_costs[ p ] += investment_costs_increment @@ -1445,6 +1473,69 @@ def _objective_expression(self): return self.costs + def _evaluate_remaining_value_difference( + self, + m, + p, + g, + end_year_of_optimization, + lifetime, + interest, + ): + """Evaluate and return the remaining value difference of an investment + + The remaining value difference in the net present values if the asset + was to be liquidated at the end of the optimization horizon and the + net present value using the original investment expenses. + + Parameters + ---------- + m : oemof.solph.models.Model + Optimization model + + p : int + Period in which investment occurs + + g : oemof.solph.components.experimental.SinkDSM + storage unit + + end_year_of_optimization : int + Last year of the optimization horizon + + lifetime : int + lifetime of investment considered + + interest : float + Demanded interest rate for investment + """ + if m.es.use_remaining_value: + if end_year_of_optimization - m.es.periods_years[p] < lifetime: + remaining_lifetime = lifetime - ( + end_year_of_optimization - m.es.periods_years[p] + ) + remaining_annuity = economics.annuity( + capex=g.investment.ep_costs[-1], + n=remaining_lifetime, + wacc=interest, + ) + original_annuity = economics.annuity( + capex=g.investment.ep_costs[p], + n=remaining_lifetime, + wacc=interest, + ) + present_value_factor_remaining = 1 / economics.annuity( + capex=1, n=remaining_lifetime, wacc=interest + ) + return ( + self.invest[g, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + else: + return 0 + else: + return 0 + class SinkDSMDIWBlock(ScalarBlock): r"""Constraints for SinkDSM with "DIW" approach @@ -2224,6 +2315,21 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): &\\ & \quad \quad \quad \quad \forall p \in \mathbb{P} + In case, the remaining lifetime of a DSM unit is greater than 0 and + attribute `use_remaining_value` of the energy system is True, + the difference in value for the investment period compared to the + last period of the optimization horizon is accounted for + as an adder to the investment costs: + + .. math:: + & + P_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - + A(c_{invest,var}(|P|), l_{r}, ir)\\ + & \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\ + &\\ + & + \forall p \in \textrm{PERIODS} + * :attr:`fixed_costs` not None for investments .. math:: @@ -3140,7 +3246,20 @@ def _objective_expression(self): investment_costs_increment = ( self.invest[g, p] * annuity * present_value_factor ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) - investment_costs += investment_costs_increment + remaining_value_difference = ( + self._evaluate_remaining_value_difference( + m, + p, + g, + m.es.end_year_of_optimization, + lifetime, + interest, + ) + ) + investment_costs += ( + investment_costs_increment + + remaining_value_difference + ) period_investment_costs[ p ] += investment_costs_increment @@ -3208,6 +3327,69 @@ def _objective_expression(self): return self.costs + def _evaluate_remaining_value_difference( + self, + m, + p, + g, + end_year_of_optimization, + lifetime, + interest, + ): + """Evaluate and return the remaining value difference of an investment + + The remaining value difference in the net present values if the asset + was to be liquidated at the end of the optimization horizon and the + net present value using the original investment expenses. + + Parameters + ---------- + m : oemof.solph.models.Model + Optimization model + + p : int + Period in which investment occurs + + g : oemof.solph.components.experimental.SinkDSM + storage unit + + end_year_of_optimization : int + Last year of the optimization horizon + + lifetime : int + lifetime of investment considered + + interest : float + Demanded interest rate for investment + """ + if m.es.use_remaining_value: + if end_year_of_optimization - m.es.periods_years[p] < lifetime: + remaining_lifetime = lifetime - ( + end_year_of_optimization - m.es.periods_years[p] + ) + remaining_annuity = economics.annuity( + capex=g.investment.ep_costs[-1], + n=remaining_lifetime, + wacc=interest, + ) + original_annuity = economics.annuity( + capex=g.investment.ep_costs[p], + n=remaining_lifetime, + wacc=interest, + ) + present_value_factor_remaining = 1 / economics.annuity( + capex=1, n=remaining_lifetime, wacc=interest + ) + return ( + self.invest[g, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + else: + return 0 + else: + return 0 + class SinkDSMDLRBlock(ScalarBlock): r"""Constraints for SinkDSM with "DLR" approach @@ -4399,6 +4581,21 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): & \forall p \in \mathbb{P} + In case, the remaining lifetime of a DSM unit is greater than 0 and + attribute `use_remaining_value` of the energy system is True, + the difference in value for the investment period compared to the + last period of the optimization horizon is accounted for + as an adder to the investment costs: + + .. math:: + & + P_{invest}(p) \cdot (A(c_{invest,var}(p), l_{r}, ir) - + A(c_{invest,var}(|P|), l_{r}, ir)\\ + & \cdot \frac {1}{ANF(l_{r}, ir)} \cdot DF^{-|P|}\\ + &\\ + & + \forall p \in \textrm{PERIODS} + * :attr:`fixed_costs` not None for investments .. math:: @@ -5541,7 +5738,20 @@ def _objective_expression(self): investment_costs_increment = ( self.invest[g, p] * annuity * present_value_factor ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) - investment_costs += investment_costs_increment + remaining_value_difference = ( + self._evaluate_remaining_value_difference( + m, + p, + g, + m.es.end_year_of_optimization, + lifetime, + interest, + ) + ) + investment_costs += ( + investment_costs_increment + + remaining_value_difference + ) period_investment_costs[ p ] += investment_costs_increment @@ -5615,3 +5825,66 @@ def _objective_expression(self): ) return self.costs + + def _evaluate_remaining_value_difference( + self, + m, + p, + g, + end_year_of_optimization, + lifetime, + interest, + ): + """Evaluate and return the remaining value difference of an investment + + The remaining value difference in the net present values if the asset + was to be liquidated at the end of the optimization horizon and the + net present value using the original investment expenses. + + Parameters + ---------- + m : oemof.solph.models.Model + Optimization model + + p : int + Period in which investment occurs + + g : oemof.solph.components.experimental.SinkDSM + storage unit + + end_year_of_optimization : int + Last year of the optimization horizon + + lifetime : int + lifetime of investment considered + + interest : float + Demanded interest rate for investment + """ + if m.es.use_remaining_value: + if end_year_of_optimization - m.es.periods_years[p] < lifetime: + remaining_lifetime = lifetime - ( + end_year_of_optimization - m.es.periods_years[p] + ) + remaining_annuity = economics.annuity( + capex=g.investment.ep_costs[-1], + n=remaining_lifetime, + wacc=interest, + ) + original_annuity = economics.annuity( + capex=g.investment.ep_costs[p], + n=remaining_lifetime, + wacc=interest, + ) + present_value_factor_remaining = 1 / economics.annuity( + capex=1, n=remaining_lifetime, wacc=interest + ) + return ( + self.invest[g, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + else: + return 0 + else: + return 0 From b8d08f73953dd4286f19f542a1b5e8dc3c9b60d1 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 16:51:49 +0200 Subject: [PATCH 075/180] Extend changelog and usage docs --- docs/usage.rst | 5 +++++ docs/whatsnew/v0-5-2.rst | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/docs/usage.rst b/docs/usage.rst index c8f0c5f0f..a160a6c83 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1270,6 +1270,11 @@ Besides the `invest` variable, new variables are introduced as well. These are: has not yet been tested. * For now, both, the `timeindex` as well as the `timeincrement` of an energy system have to be defined since they have to be of the same length for a multi-period model. + * You can choose whether or not to re-evaluate assets at the end of the optimization horizon. If you set attribute + `use_remaining_value` of the energy system to True (defaults to False), this leads to the model evaluating the + different in value at the end of the optimization horizon vs. at the time the investment was made. The difference + in value is added to or subtracted from the respective investment costs increment, assuming assets are to be + liquidated / re-evaluated at the end of the optimization horizon. * Also please be aware, that periods correspond to years by default. You could also choose monthly periods, but you would need to be very careful in parameterizing your energy system and your model and also, this would mean monthly discounting (if applicable) as well as specifying your plants lifetimes in months. diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index 0cdf89701..6859e1652 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -4,9 +4,14 @@ v0.5.2 (????) API changes ########### +* New bool attribute `use_remaining_value` of `oemof.solph.EnergySystem` + New features ############ +* Allow for evaluating differences in the remaining vs. the original value + for multi-period investments. + Documentation ############# From 22b4519c96178526b4f384134c6dd67bd48854ad Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 17:04:22 +0200 Subject: [PATCH 076/180] Add new constraint tests --- ...DIW_invest_multi_period_remaining_value.lp | 487 +++++++++++ ...DLR_invest_multi_period_remaining_value.lp | 824 ++++++++++++++++++ ...mof_invest_multi_period_remaining_value.lp | 301 +++++++ ...ter_invest_multi_period_remaining_value.lp | 230 +++++ ...e_invest_1_multi_period_remaining_value.lp | 505 +++++++++++ tests/multi_period_constraint_tests.py | 185 ++++ 6 files changed, 2532 insertions(+) create mode 100644 tests/lp_files/dsm_module_DIW_invest_multi_period_remaining_value.lp create mode 100644 tests/lp_files/dsm_module_DLR_invest_multi_period_remaining_value.lp create mode 100644 tests/lp_files/dsm_module_oemof_invest_multi_period_remaining_value.lp create mode 100644 tests/lp_files/linear_converter_invest_multi_period_remaining_value.lp create mode 100644 tests/lp_files/storage_invest_1_multi_period_remaining_value.lp diff --git a/tests/lp_files/dsm_module_DIW_invest_multi_period_remaining_value.lp b/tests/lp_files/dsm_module_DIW_invest_multi_period_remaining_value.lp new file mode 100644 index 000000000..e8f35046c --- /dev/null +++ b/tests/lp_files/dsm_module_DIW_invest_multi_period_remaining_value.lp @@ -0,0 +1,487 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++2941.5609381007307 ONE_VAR_CONSTANT ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_0) ++100 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_0) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_0) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_1) ++100 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_1) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_2) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_2) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_2) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_2) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_2) ++98.0392156862745 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_2) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_3) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_3) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_3) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_3) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_3) ++0.9803921568627451 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_3) ++98.0392156862745 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_3) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_4) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_4) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_4) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_4) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_4) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_4) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_4) ++96.11687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_4) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_5) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_5) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_5) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_5) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_5) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_5) ++0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) ++96.11687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) ++57.62165571222974 SinkDSMDIWInvestmentBlock_invest(demand_dsm_0) ++39.12361323621548 SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) ++23.087255832295018 SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) + +s.t. + +c_e_BusBlock_balance(bus_elec_0_0)_: ++1 flow(bus_elec_demand_dsm_0_0) += 0 + +c_e_BusBlock_balance(bus_elec_0_1)_: ++1 flow(bus_elec_demand_dsm_0_1) += 0 + +c_e_BusBlock_balance(bus_elec_1_2)_: ++1 flow(bus_elec_demand_dsm_1_2) += 0 + +c_e_BusBlock_balance(bus_elec_1_3)_: ++1 flow(bus_elec_demand_dsm_1_3) += 0 + +c_e_BusBlock_balance(bus_elec_2_4)_: ++1 flow(bus_elec_demand_dsm_2_4) += 0 + +c_e_BusBlock_balance(bus_elec_2_5)_: ++1 flow(bus_elec_demand_dsm_2_5) += 0 + +c_e_SinkDSMDIWInvestmentBlock_total_dsm_rule(demand_dsm_0)_: +-1 SinkDSMDIWInvestmentBlock_invest(demand_dsm_0) ++1 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) += 50 + +c_e_SinkDSMDIWInvestmentBlock_total_dsm_rule(demand_dsm_1)_: +-1 SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) +-1 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) ++1 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMDIWInvestmentBlock_old(demand_dsm_1) += 0 + +c_e_SinkDSMDIWInvestmentBlock_total_dsm_rule(demand_dsm_2)_: +-1 SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) +-1 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) ++1 SinkDSMDIWInvestmentBlock_old(demand_dsm_2) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule_end(demand_dsm_0)_: ++1 SinkDSMDIWInvestmentBlock_old_end(demand_dsm_0) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule_end(demand_dsm_1)_: ++1 SinkDSMDIWInvestmentBlock_old_end(demand_dsm_1) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule_end(demand_dsm_2)_: ++1 SinkDSMDIWInvestmentBlock_old_end(demand_dsm_2) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule_exo(demand_dsm_0)_: ++1 SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_0) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule_exo(demand_dsm_1)_: ++1 SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_1) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule_exo(demand_dsm_2)_: ++1 SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_2) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule(demand_dsm_0)_: +-1 SinkDSMDIWInvestmentBlock_old_end(demand_dsm_0) +-1 SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_0) ++1 SinkDSMDIWInvestmentBlock_old(demand_dsm_0) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule(demand_dsm_1)_: ++1 SinkDSMDIWInvestmentBlock_old(demand_dsm_1) +-1 SinkDSMDIWInvestmentBlock_old_end(demand_dsm_1) +-1 SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_1) += 0 + +c_e_SinkDSMDIWInvestmentBlock_old_dsm_rule(demand_dsm_2)_: ++1 SinkDSMDIWInvestmentBlock_old(demand_dsm_2) +-1 SinkDSMDIWInvestmentBlock_old_end(demand_dsm_2) +-1 SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_2) += 0 + +c_e_SinkDSMDIWInvestmentBlock_input_output_relation(demand_dsm_0_0)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_0) +-1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_0) ++1 flow(bus_elec_demand_dsm_0_0) += 1 + +c_e_SinkDSMDIWInvestmentBlock_input_output_relation(demand_dsm_0_1)_: +-1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_1) ++1 flow(bus_elec_demand_dsm_0_1) += 1 + +c_e_SinkDSMDIWInvestmentBlock_input_output_relation(demand_dsm_1_2)_: +-1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_2) ++1 flow(bus_elec_demand_dsm_1_2) += 2 + +c_e_SinkDSMDIWInvestmentBlock_input_output_relation(demand_dsm_1_3)_: +-1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_3) ++1 flow(bus_elec_demand_dsm_1_3) += 2 + +c_e_SinkDSMDIWInvestmentBlock_input_output_relation(demand_dsm_2_4)_: +-1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_4) ++1 flow(bus_elec_demand_dsm_2_4) += 3 + +c_e_SinkDSMDIWInvestmentBlock_input_output_relation(demand_dsm_2_5)_: +-1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_5) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_5) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) ++1 flow(bus_elec_demand_dsm_2_5) += 3 + +c_e_SinkDSMDIWInvestmentBlock_dsm_updo_constraint(demand_dsm_0)_: +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_0) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_0) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_1) += 0 + +c_e_SinkDSMDIWInvestmentBlock_dsm_updo_constraint(demand_dsm_1)_: +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_1) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_1) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_2) += 0 + +c_e_SinkDSMDIWInvestmentBlock_dsm_updo_constraint(demand_dsm_2)_: +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_2) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_2) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_3) += 0 + +c_e_SinkDSMDIWInvestmentBlock_dsm_updo_constraint(demand_dsm_3)_: +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_2) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_3) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_3) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_4) += 0 + +c_e_SinkDSMDIWInvestmentBlock_dsm_updo_constraint(demand_dsm_4)_: +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_3) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_4) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_4) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_5) += 0 + +c_e_SinkDSMDIWInvestmentBlock_dsm_updo_constraint(demand_dsm_5)_: +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_4) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_5) +-1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) += 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_up_constraint(demand_dsm_0_0)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_0) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_up_constraint(demand_dsm_0_1)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_1) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_up_constraint(demand_dsm_1_2)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_2) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_up_constraint(demand_dsm_1_3)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_3) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_up_constraint(demand_dsm_2_4)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_4) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_up_constraint(demand_dsm_2_5)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_5) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_do_constraint(demand_dsm_0_0)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_0) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_do_constraint(demand_dsm_0_1)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_1) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_do_constraint(demand_dsm_1_2)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_2) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_do_constraint(demand_dsm_1_3)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_3) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_do_constraint(demand_dsm_2_4)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_4) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_dsm_do_constraint(demand_dsm_2_5)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_5) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_C2_constraint(demand_dsm_0_0)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_0) ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_0) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_C2_constraint(demand_dsm_0_1)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_1) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_C2_constraint(demand_dsm_1_2)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_2) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_C2_constraint(demand_dsm_1_3)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_3) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_C2_constraint(demand_dsm_2_4)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_4) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_C2_constraint(demand_dsm_2_5)_: ++1 SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_5) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_5) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) +-0.5 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_shed_limit_constraint(demand_dsm_0_0)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_0) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_1) +-1.0 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_shed_limit_constraint(demand_dsm_0_1)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_1) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_2) +-1.0 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_shed_limit_constraint(demand_dsm_1_2)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_2) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_3) +-1.0 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_shed_limit_constraint(demand_dsm_1_3)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_3) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_4) +-1.0 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_shed_limit_constraint(demand_dsm_2_4)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_4) ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) +-1.0 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_shed_limit_constraint(demand_dsm_2_5)_: ++1 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) +-1.0 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDIWInvestmentBlock_overall_dsm_maximum(demand_dsm_0)_: ++1 SinkDSMDIWInvestmentBlock_total(demand_dsm_0) +<= 1000 + +c_u_SinkDSMDIWInvestmentBlock_overall_dsm_maximum(demand_dsm_1)_: ++1 SinkDSMDIWInvestmentBlock_total(demand_dsm_1) +<= 1000 + +c_u_SinkDSMDIWInvestmentBlock_overall_dsm_maximum(demand_dsm_2)_: ++1 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +<= 1000 + +c_l_SinkDSMDIWInvestmentBlock_overall_minimum(demand_dsm)_: ++1 SinkDSMDIWInvestmentBlock_total(demand_dsm_2) +>= 5 + +bounds + 1 <= ONE_VAR_CONSTANT <= 1 + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_3) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_3) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_3) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_3) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_3) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_3) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_3) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_3) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_4) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_4) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_4) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_4) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_4) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_4) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_4) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_4) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_up(demand_dsm_5) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_0_5) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_1_5) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_2_5) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_3_5) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_4_5) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) <= +inf + 33 <= SinkDSMDIWInvestmentBlock_invest(demand_dsm_0) <= 100 + 33 <= SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) <= 100 + 33 <= SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) <= 100 + 0 <= flow(bus_elec_demand_dsm_0_0) <= +inf + 0 <= flow(bus_elec_demand_dsm_0_1) <= +inf + 0 <= flow(bus_elec_demand_dsm_1_2) <= +inf + 0 <= flow(bus_elec_demand_dsm_1_3) <= +inf + 0 <= flow(bus_elec_demand_dsm_2_4) <= +inf + 0 <= flow(bus_elec_demand_dsm_2_5) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_total(demand_dsm_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_total(demand_dsm_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old(demand_dsm_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_total(demand_dsm_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old(demand_dsm_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old_end(demand_dsm_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old_end(demand_dsm_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old_end(demand_dsm_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_0) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_1) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old_exo(demand_dsm_2) <= +inf + 0 <= SinkDSMDIWInvestmentBlock_old(demand_dsm_0) <= +inf +end diff --git a/tests/lp_files/dsm_module_DLR_invest_multi_period_remaining_value.lp b/tests/lp_files/dsm_module_DLR_invest_multi_period_remaining_value.lp new file mode 100644 index 000000000..d543924d8 --- /dev/null +++ b/tests/lp_files/dsm_module_DLR_invest_multi_period_remaining_value.lp @@ -0,0 +1,824 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++2941.5609381007307 ONE_VAR_CONSTANT ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_0) ++100 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_1) ++100 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_1) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_2) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_2) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_2) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_2) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_2) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_2) ++98.0392156862745 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_2) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_3) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_3) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_3) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_3) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_3) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_3) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++0.9803921568627451 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_3) ++98.0392156862745 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_3) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_4) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_4) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_4) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_4) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_4) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_4) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_4) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_4) ++96.11687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_4) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_5) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_5) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_5) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_5) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_5) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_5) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_5) ++0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) ++96.11687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) ++57.62165571222974 SinkDSMDLRInvestmentBlock_invest(demand_dsm_0) ++39.12361323621548 SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) ++23.087255832295018 SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) + +s.t. + +c_e_BusBlock_balance(bus_elec_0_0)_: ++1 flow(bus_elec_demand_dsm_0_0) += 0 + +c_e_BusBlock_balance(bus_elec_0_1)_: ++1 flow(bus_elec_demand_dsm_0_1) += 0 + +c_e_BusBlock_balance(bus_elec_1_2)_: ++1 flow(bus_elec_demand_dsm_1_2) += 0 + +c_e_BusBlock_balance(bus_elec_1_3)_: ++1 flow(bus_elec_demand_dsm_1_3) += 0 + +c_e_BusBlock_balance(bus_elec_2_4)_: ++1 flow(bus_elec_demand_dsm_2_4) += 0 + +c_e_BusBlock_balance(bus_elec_2_5)_: ++1 flow(bus_elec_demand_dsm_2_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_total_dsm_rule(demand_dsm_0)_: +-1 SinkDSMDLRInvestmentBlock_invest(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) += 50 + +c_e_SinkDSMDLRInvestmentBlock_total_dsm_rule(demand_dsm_1)_: +-1 SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) +-1 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMDLRInvestmentBlock_old(demand_dsm_1) += 0 + +c_e_SinkDSMDLRInvestmentBlock_total_dsm_rule(demand_dsm_2)_: +-1 SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) +-1 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) ++1 SinkDSMDLRInvestmentBlock_old(demand_dsm_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule_end(demand_dsm_0)_: ++1 SinkDSMDLRInvestmentBlock_old_end(demand_dsm_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule_end(demand_dsm_1)_: ++1 SinkDSMDLRInvestmentBlock_old_end(demand_dsm_1) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule_end(demand_dsm_2)_: ++1 SinkDSMDLRInvestmentBlock_old_end(demand_dsm_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule_exo(demand_dsm_0)_: ++1 SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule_exo(demand_dsm_1)_: ++1 SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_1) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule_exo(demand_dsm_2)_: ++1 SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule(demand_dsm_0)_: +-1 SinkDSMDLRInvestmentBlock_old_end(demand_dsm_0) +-1 SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_old(demand_dsm_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule(demand_dsm_1)_: ++1 SinkDSMDLRInvestmentBlock_old(demand_dsm_1) +-1 SinkDSMDLRInvestmentBlock_old_end(demand_dsm_1) +-1 SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_1) += 0 + +c_e_SinkDSMDLRInvestmentBlock_old_dsm_rule(demand_dsm_2)_: ++1 SinkDSMDLRInvestmentBlock_old(demand_dsm_2) +-1 SinkDSMDLRInvestmentBlock_old_end(demand_dsm_2) +-1 SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_input_output_relation(demand_dsm_0_0)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_0) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_0) +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_0) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_0) ++1 flow(bus_elec_demand_dsm_0_0) += 1 + +c_e_SinkDSMDLRInvestmentBlock_input_output_relation(demand_dsm_0_1)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_1) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_1) +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_1) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_1) ++1 flow(bus_elec_demand_dsm_0_1) += 1 + +c_e_SinkDSMDLRInvestmentBlock_input_output_relation(demand_dsm_1_2)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_2) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_2) +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_2) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_2) ++1 flow(bus_elec_demand_dsm_1_2) += 2 + +c_e_SinkDSMDLRInvestmentBlock_input_output_relation(demand_dsm_1_3)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_3) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_3) +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_3) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_3) ++1 flow(bus_elec_demand_dsm_1_3) += 2 + +c_e_SinkDSMDLRInvestmentBlock_input_output_relation(demand_dsm_2_4)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_4) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_4) +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_4) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_4) ++1 flow(bus_elec_demand_dsm_2_4) += 3 + +c_e_SinkDSMDLRInvestmentBlock_input_output_relation(demand_dsm_2_5)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_5) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_5) +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_5) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) ++1 flow(bus_elec_demand_dsm_2_5) += 3 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_1_0)_: ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_1_1)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_1) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_1_2)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_1_3)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_3) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_1_4)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_4) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_1_5)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_2_0)_: ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_2_2)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_2_3)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_3) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_2_4)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_4) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_red(demand_dsm_2_5)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_1_0)_: ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_1_1)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_1) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_1_2)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_1_3)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_3) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_1_4)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_4) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_1_5)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_2_0)_: ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_2_2)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_2_3)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_3) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_2_4)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_4) += 0 + +c_e_SinkDSMDLRInvestmentBlock_capacity_balance_inc(demand_dsm_2_5)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_no_comp_red(demand_dsm_1_5)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_no_comp_red(demand_dsm_2_4)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_4) += 0 + +c_e_SinkDSMDLRInvestmentBlock_no_comp_red(demand_dsm_2_5)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_no_comp_inc(demand_dsm_1_5)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_no_comp_inc(demand_dsm_2_4)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_4) += 0 + +c_e_SinkDSMDLRInvestmentBlock_no_comp_inc(demand_dsm_2_5)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_5) += 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_red(demand_dsm_0_0)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_0) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_red(demand_dsm_0_1)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_1) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_red(demand_dsm_1_2)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_2) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_red(demand_dsm_1_3)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_3) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_red(demand_dsm_2_4)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_4) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_red(demand_dsm_2_5)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_inc(demand_dsm_0_0)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_0) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_inc(demand_dsm_0_1)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_1) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_inc(demand_dsm_1_2)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_2) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_inc(demand_dsm_1_3)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_3) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_inc(demand_dsm_2_4)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_4) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_availability_inc(demand_dsm_2_5)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_5) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_red(demand_dsm_0)_: +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_0) +-1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_red(demand_dsm_1)_: +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_1) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_0) +-1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_1) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_red(demand_dsm_2)_: +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_2) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_1) +-1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_red(demand_dsm_3)_: +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_3) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_2) +-1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_3) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_red(demand_dsm_4)_: +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_4) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_3) +-1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_4) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_red(demand_dsm_5)_: +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_5) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_4) +-1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_5) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_inc(demand_dsm_0)_: +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_0) +-1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_0) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_inc(demand_dsm_1)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_1) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_1) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_0) +-1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_1) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_inc(demand_dsm_2)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_2) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_2) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_1) +-1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_2) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_inc(demand_dsm_3)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_3) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_3) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_2) +-1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_3) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_inc(demand_dsm_4)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_4) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_4) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_3) +-1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_4) += 0 + +c_e_SinkDSMDLRInvestmentBlock_dr_storage_inc(demand_dsm_5)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_5) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_5) +-1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_4) +-1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_5) += 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_red(demand_dsm_0_0)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_red(demand_dsm_0_1)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_red(demand_dsm_1_2)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_2) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_red(demand_dsm_1_3)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_3) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_red(demand_dsm_2_4)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_4) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_red(demand_dsm_2_5)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_5) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_inc(demand_dsm_0_0)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_inc(demand_dsm_0_1)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_inc(demand_dsm_1_2)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_2) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_inc(demand_dsm_1_3)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_3) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_inc(demand_dsm_2_4)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_4) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_storage_limit_inc(demand_dsm_2_5)_: +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) ++1 SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_5) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_yearly_limit_shed(demand_dsm_0)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_1) +-50.0 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_yearly_limit_shed(demand_dsm_1)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_3) +-50.0 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_yearly_limit_shed(demand_dsm_2)_: ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) +-50.0 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_logical_constraint(demand_dsm_0_0)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_0) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_0) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_logical_constraint(demand_dsm_0_1)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_1) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_1) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_logical_constraint(demand_dsm_1_2)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_2) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_2) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_logical_constraint(demand_dsm_1_3)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_3) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_3) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_logical_constraint(demand_dsm_2_4)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_4) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_4) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_dr_logical_constraint(demand_dsm_2_5)_: ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) ++1 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) +-0.5 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMDLRInvestmentBlock_overall_dsm_maximum(demand_dsm_0)_: ++1 SinkDSMDLRInvestmentBlock_total(demand_dsm_0) +<= 1000 + +c_u_SinkDSMDLRInvestmentBlock_overall_dsm_maximum(demand_dsm_1)_: ++1 SinkDSMDLRInvestmentBlock_total(demand_dsm_1) +<= 1000 + +c_u_SinkDSMDLRInvestmentBlock_overall_dsm_maximum(demand_dsm_2)_: ++1 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +<= 1000 + +c_l_SinkDSMDLRInvestmentBlock_overall_minimum(demand_dsm)_: ++1 SinkDSMDLRInvestmentBlock_total(demand_dsm_2) +>= 5 + +bounds + 1 <= ONE_VAR_CONSTANT <= 1 + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_1_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_1_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_2_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_2_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_1_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_1_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shift(demand_dsm_2_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) <= +inf + 33 <= SinkDSMDLRInvestmentBlock_invest(demand_dsm_0) <= 100 + 33 <= SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) <= 100 + 33 <= SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) <= 100 + 0 <= flow(bus_elec_demand_dsm_0_0) <= +inf + 0 <= flow(bus_elec_demand_dsm_0_1) <= +inf + 0 <= flow(bus_elec_demand_dsm_1_2) <= +inf + 0 <= flow(bus_elec_demand_dsm_1_3) <= +inf + 0 <= flow(bus_elec_demand_dsm_2_4) <= +inf + 0 <= flow(bus_elec_demand_dsm_2_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_total(demand_dsm_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_total(demand_dsm_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old(demand_dsm_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_total(demand_dsm_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old(demand_dsm_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old_end(demand_dsm_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old_end(demand_dsm_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old_end(demand_dsm_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old_exo(demand_dsm_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_old(demand_dsm_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_do_level(demand_dsm_5) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_0) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_1) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_2) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_3) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_4) <= +inf + 0 <= SinkDSMDLRInvestmentBlock_dsm_up_level(demand_dsm_5) <= +inf +end diff --git a/tests/lp_files/dsm_module_oemof_invest_multi_period_remaining_value.lp b/tests/lp_files/dsm_module_oemof_invest_multi_period_remaining_value.lp new file mode 100644 index 000000000..0baff5cc8 --- /dev/null +++ b/tests/lp_files/dsm_module_oemof_invest_multi_period_remaining_value.lp @@ -0,0 +1,301 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++2941.5609381007307 ONE_VAR_CONSTANT ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_0) ++100 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_1) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_1) ++100 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_1) ++0.9803921568627451 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_2) ++0.9803921568627451 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_2) ++98.0392156862745 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_2) ++0.9803921568627451 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_3) ++0.9803921568627451 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_3) ++98.0392156862745 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_3) ++0.9611687812379853 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_4) ++0.9611687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_4) ++96.11687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_4) ++0.9611687812379853 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_5) ++0.9611687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_5) ++96.11687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_5) ++57.62165571222974 SinkDSMOemofInvestmentBlock_invest(demand_dsm_0) ++39.12361323621548 SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) ++23.087255832295018 SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) + +s.t. + +c_e_BusBlock_balance(bus_elec_0_0)_: ++1 flow(bus_elec_demand_dsm_0_0) += 0 + +c_e_BusBlock_balance(bus_elec_0_1)_: ++1 flow(bus_elec_demand_dsm_0_1) += 0 + +c_e_BusBlock_balance(bus_elec_1_2)_: ++1 flow(bus_elec_demand_dsm_1_2) += 0 + +c_e_BusBlock_balance(bus_elec_1_3)_: ++1 flow(bus_elec_demand_dsm_1_3) += 0 + +c_e_BusBlock_balance(bus_elec_2_4)_: ++1 flow(bus_elec_demand_dsm_2_4) += 0 + +c_e_BusBlock_balance(bus_elec_2_5)_: ++1 flow(bus_elec_demand_dsm_2_5) += 0 + +c_e_SinkDSMOemofInvestmentBlock_total_dsm_rule(demand_dsm_0)_: +-1 SinkDSMOemofInvestmentBlock_invest(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_total(demand_dsm_0) += 50 + +c_e_SinkDSMOemofInvestmentBlock_total_dsm_rule(demand_dsm_1)_: +-1 SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) +-1 SinkDSMOemofInvestmentBlock_total(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMOemofInvestmentBlock_old(demand_dsm_1) += 0 + +c_e_SinkDSMOemofInvestmentBlock_total_dsm_rule(demand_dsm_2)_: +-1 SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) +-1 SinkDSMOemofInvestmentBlock_total(demand_dsm_1) ++1 SinkDSMOemofInvestmentBlock_total(demand_dsm_2) ++1 SinkDSMOemofInvestmentBlock_old(demand_dsm_2) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule_end(demand_dsm_0)_: ++1 SinkDSMOemofInvestmentBlock_old_end(demand_dsm_0) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule_end(demand_dsm_1)_: ++1 SinkDSMOemofInvestmentBlock_old_end(demand_dsm_1) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule_end(demand_dsm_2)_: ++1 SinkDSMOemofInvestmentBlock_old_end(demand_dsm_2) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule_exo(demand_dsm_0)_: ++1 SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_0) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule_exo(demand_dsm_1)_: ++1 SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_1) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule_exo(demand_dsm_2)_: ++1 SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_2) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule(demand_dsm_0)_: +-1 SinkDSMOemofInvestmentBlock_old_end(demand_dsm_0) +-1 SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_old(demand_dsm_0) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule(demand_dsm_1)_: ++1 SinkDSMOemofInvestmentBlock_old(demand_dsm_1) +-1 SinkDSMOemofInvestmentBlock_old_end(demand_dsm_1) +-1 SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_1) += 0 + +c_e_SinkDSMOemofInvestmentBlock_old_dsm_rule(demand_dsm_2)_: ++1 SinkDSMOemofInvestmentBlock_old(demand_dsm_2) +-1 SinkDSMOemofInvestmentBlock_old_end(demand_dsm_2) +-1 SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_2) += 0 + +c_e_SinkDSMOemofInvestmentBlock_input_output_relation(demand_dsm_0_0)_: ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_0) +-1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_0) ++1 flow(bus_elec_demand_dsm_0_0) += 1 + +c_e_SinkDSMOemofInvestmentBlock_input_output_relation(demand_dsm_0_1)_: +-1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_1) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_1) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_1) ++1 flow(bus_elec_demand_dsm_0_1) += 1 + +c_e_SinkDSMOemofInvestmentBlock_input_output_relation(demand_dsm_1_2)_: +-1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_2) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_2) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_2) ++1 flow(bus_elec_demand_dsm_1_2) += 2 + +c_e_SinkDSMOemofInvestmentBlock_input_output_relation(demand_dsm_1_3)_: +-1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_3) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_3) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_3) ++1 flow(bus_elec_demand_dsm_1_3) += 2 + +c_e_SinkDSMOemofInvestmentBlock_input_output_relation(demand_dsm_2_4)_: +-1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_4) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_4) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_4) ++1 flow(bus_elec_demand_dsm_2_4) += 3 + +c_e_SinkDSMOemofInvestmentBlock_input_output_relation(demand_dsm_2_5)_: +-1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_5) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_5) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_5) ++1 flow(bus_elec_demand_dsm_2_5) += 3 + +c_u_SinkDSMOemofInvestmentBlock_dsm_up_constraint(demand_dsm_0_0)_: ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_0) +-0.5 SinkDSMOemofInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_up_constraint(demand_dsm_0_1)_: ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_1) +-0.4 SinkDSMOemofInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_up_constraint(demand_dsm_1_2)_: ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_2) +-0.5 SinkDSMOemofInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_up_constraint(demand_dsm_1_3)_: ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_3) +-0.3 SinkDSMOemofInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_up_constraint(demand_dsm_2_4)_: ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_4) +-0.3 SinkDSMOemofInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_up_constraint(demand_dsm_2_5)_: ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_5) +-0.3 SinkDSMOemofInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_down_constraint(demand_dsm_0_0)_: ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_0) +-0.5 SinkDSMOemofInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_down_constraint(demand_dsm_0_1)_: ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_1) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_1) +-0.4 SinkDSMOemofInvestmentBlock_total(demand_dsm_0) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_down_constraint(demand_dsm_1_2)_: ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_2) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_2) +-0.5 SinkDSMOemofInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_down_constraint(demand_dsm_1_3)_: ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_3) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_3) +-0.3 SinkDSMOemofInvestmentBlock_total(demand_dsm_1) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_down_constraint(demand_dsm_2_4)_: ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_4) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_4) +-0.3 SinkDSMOemofInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_u_SinkDSMOemofInvestmentBlock_dsm_down_constraint(demand_dsm_2_5)_: ++1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_5) ++1 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_5) +-0.3 SinkDSMOemofInvestmentBlock_total(demand_dsm_2) +<= 0 + +c_e_SinkDSMOemofInvestmentBlock_dsm_sum_constraint(demand_dsm_0)_: +-1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_0) ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_1) +-1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_1) += 0 + +c_e_SinkDSMOemofInvestmentBlock_dsm_sum_constraint(demand_dsm_2)_: ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_2) +-1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_2) ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_3) +-1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_3) += 0 + +c_e_SinkDSMOemofInvestmentBlock_dsm_sum_constraint(demand_dsm_4)_: ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_4) +-1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_4) ++1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_5) +-1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_5) += 0 + +c_u_SinkDSMOemofInvestmentBlock_overall_dsm_maximum(demand_dsm_0)_: ++1 SinkDSMOemofInvestmentBlock_total(demand_dsm_0) +<= 1000 + +c_u_SinkDSMOemofInvestmentBlock_overall_dsm_maximum(demand_dsm_1)_: ++1 SinkDSMOemofInvestmentBlock_total(demand_dsm_1) +<= 1000 + +c_u_SinkDSMOemofInvestmentBlock_overall_dsm_maximum(demand_dsm_2)_: ++1 SinkDSMOemofInvestmentBlock_total(demand_dsm_2) +<= 1000 + +c_l_SinkDSMOemofInvestmentBlock_overall_minimum(demand_dsm)_: ++1 SinkDSMOemofInvestmentBlock_total(demand_dsm_2) +>= 5 + +bounds + 1 <= ONE_VAR_CONSTANT <= 1 + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_0) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_0) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_0) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_1) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_1) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_1) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_2) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_2) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_2) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_3) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_3) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_3) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_4) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_4) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_4) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_5) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_5) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_5) <= +inf + 33 <= SinkDSMOemofInvestmentBlock_invest(demand_dsm_0) <= 100 + 33 <= SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) <= 100 + 33 <= SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) <= 100 + 0 <= flow(bus_elec_demand_dsm_0_0) <= +inf + 0 <= flow(bus_elec_demand_dsm_0_1) <= +inf + 0 <= flow(bus_elec_demand_dsm_1_2) <= +inf + 0 <= flow(bus_elec_demand_dsm_1_3) <= +inf + 0 <= flow(bus_elec_demand_dsm_2_4) <= +inf + 0 <= flow(bus_elec_demand_dsm_2_5) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_total(demand_dsm_0) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_total(demand_dsm_1) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old(demand_dsm_1) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_total(demand_dsm_2) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old(demand_dsm_2) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old_end(demand_dsm_0) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old_end(demand_dsm_1) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old_end(demand_dsm_2) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_0) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_1) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old_exo(demand_dsm_2) <= +inf + 0 <= SinkDSMOemofInvestmentBlock_old(demand_dsm_0) <= +inf +end diff --git a/tests/lp_files/linear_converter_invest_multi_period_remaining_value.lp b/tests/lp_files/linear_converter_invest_multi_period_remaining_value.lp new file mode 100644 index 000000000..87890c538 --- /dev/null +++ b/tests/lp_files/linear_converter_invest_multi_period_remaining_value.lp @@ -0,0 +1,230 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++0.22380552274393728 InvestmentFlowBlock_invest(powerplant_gas_electricity_0) ++0.37976494755240464 InvestmentFlowBlock_invest(powerplant_gas_electricity_1) ++0.6200513568991706 InvestmentFlowBlock_invest(powerplant_gas_electricity_2) ++50 flow(powerplant_gas_electricity_0_0) ++50 flow(powerplant_gas_electricity_0_1) ++49.01960784313725 flow(powerplant_gas_electricity_1_2) ++49.01960784313725 flow(powerplant_gas_electricity_1_3) ++48.058439061899264 flow(powerplant_gas_electricity_2_4) ++48.058439061899264 flow(powerplant_gas_electricity_2_5) + +s.t. + +c_e_BusBlock_balance(gas_0_0)_: ++1 flow(gas_powerplant_gas_0_0) += 0 + +c_e_BusBlock_balance(gas_0_1)_: ++1 flow(gas_powerplant_gas_0_1) += 0 + +c_e_BusBlock_balance(gas_1_2)_: ++1 flow(gas_powerplant_gas_1_2) += 0 + +c_e_BusBlock_balance(gas_1_3)_: ++1 flow(gas_powerplant_gas_1_3) += 0 + +c_e_BusBlock_balance(gas_2_4)_: ++1 flow(gas_powerplant_gas_2_4) += 0 + +c_e_BusBlock_balance(gas_2_5)_: ++1 flow(gas_powerplant_gas_2_5) += 0 + +c_e_BusBlock_balance(electricity_0_0)_: ++1 flow(powerplant_gas_electricity_0_0) += 0 + +c_e_BusBlock_balance(electricity_0_1)_: ++1 flow(powerplant_gas_electricity_0_1) += 0 + +c_e_BusBlock_balance(electricity_1_2)_: ++1 flow(powerplant_gas_electricity_1_2) += 0 + +c_e_BusBlock_balance(electricity_1_3)_: ++1 flow(powerplant_gas_electricity_1_3) += 0 + +c_e_BusBlock_balance(electricity_2_4)_: ++1 flow(powerplant_gas_electricity_2_4) += 0 + +c_e_BusBlock_balance(electricity_2_5)_: ++1 flow(powerplant_gas_electricity_2_5) += 0 + +c_e_ConverterBlock_relation(powerplant_gas_gas_electricity_0_0)_: +-1 flow(powerplant_gas_electricity_0_0) ++0.58 flow(gas_powerplant_gas_0_0) += 0 + +c_e_ConverterBlock_relation(powerplant_gas_gas_electricity_0_1)_: +-1 flow(powerplant_gas_electricity_0_1) ++0.58 flow(gas_powerplant_gas_0_1) += 0 + +c_e_ConverterBlock_relation(powerplant_gas_gas_electricity_1_2)_: +-1 flow(powerplant_gas_electricity_1_2) ++0.58 flow(gas_powerplant_gas_1_2) += 0 + +c_e_ConverterBlock_relation(powerplant_gas_gas_electricity_1_3)_: +-1 flow(powerplant_gas_electricity_1_3) ++0.58 flow(gas_powerplant_gas_1_3) += 0 + +c_e_ConverterBlock_relation(powerplant_gas_gas_electricity_2_4)_: +-1 flow(powerplant_gas_electricity_2_4) ++0.58 flow(gas_powerplant_gas_2_4) += 0 + +c_e_ConverterBlock_relation(powerplant_gas_gas_electricity_2_5)_: +-1 flow(powerplant_gas_electricity_2_5) ++0.58 flow(gas_powerplant_gas_2_5) += 0 + +c_e_InvestmentFlowBlock_total_rule(powerplant_gas_electricity_0)_: +-1 InvestmentFlowBlock_invest(powerplant_gas_electricity_0) ++1 InvestmentFlowBlock_total(powerplant_gas_electricity_0) += 50 + +c_e_InvestmentFlowBlock_total_rule(powerplant_gas_electricity_1)_: +-1 InvestmentFlowBlock_invest(powerplant_gas_electricity_1) +-1 InvestmentFlowBlock_total(powerplant_gas_electricity_0) ++1 InvestmentFlowBlock_total(powerplant_gas_electricity_1) ++1 InvestmentFlowBlock_old(powerplant_gas_electricity_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(powerplant_gas_electricity_2)_: +-1 InvestmentFlowBlock_invest(powerplant_gas_electricity_2) +-1 InvestmentFlowBlock_total(powerplant_gas_electricity_1) ++1 InvestmentFlowBlock_total(powerplant_gas_electricity_2) ++1 InvestmentFlowBlock_old(powerplant_gas_electricity_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(powerplant_gas_electricity_0)_: ++1 InvestmentFlowBlock_old_end(powerplant_gas_electricity_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(powerplant_gas_electricity_1)_: ++1 InvestmentFlowBlock_old_end(powerplant_gas_electricity_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(powerplant_gas_electricity_2)_: ++1 InvestmentFlowBlock_old_end(powerplant_gas_electricity_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(powerplant_gas_electricity_0)_: ++1 InvestmentFlowBlock_old_exo(powerplant_gas_electricity_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(powerplant_gas_electricity_1)_: ++1 InvestmentFlowBlock_old_exo(powerplant_gas_electricity_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(powerplant_gas_electricity_2)_: ++1 InvestmentFlowBlock_old_exo(powerplant_gas_electricity_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(powerplant_gas_electricity_0)_: +-1 InvestmentFlowBlock_old_end(powerplant_gas_electricity_0) +-1 InvestmentFlowBlock_old_exo(powerplant_gas_electricity_0) ++1 InvestmentFlowBlock_old(powerplant_gas_electricity_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(powerplant_gas_electricity_1)_: ++1 InvestmentFlowBlock_old(powerplant_gas_electricity_1) +-1 InvestmentFlowBlock_old_end(powerplant_gas_electricity_1) +-1 InvestmentFlowBlock_old_exo(powerplant_gas_electricity_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(powerplant_gas_electricity_2)_: ++1 InvestmentFlowBlock_old(powerplant_gas_electricity_2) +-1 InvestmentFlowBlock_old_end(powerplant_gas_electricity_2) +-1 InvestmentFlowBlock_old_exo(powerplant_gas_electricity_2) += 0 + +c_u_InvestmentFlowBlock_max(powerplant_gas_electricity_0_0)_: ++1 flow(powerplant_gas_electricity_0_0) +-1 InvestmentFlowBlock_total(powerplant_gas_electricity_0) +<= 0 + +c_u_InvestmentFlowBlock_max(powerplant_gas_electricity_0_1)_: ++1 flow(powerplant_gas_electricity_0_1) +-1 InvestmentFlowBlock_total(powerplant_gas_electricity_0) +<= 0 + +c_u_InvestmentFlowBlock_max(powerplant_gas_electricity_1_2)_: ++1 flow(powerplant_gas_electricity_1_2) +-1 InvestmentFlowBlock_total(powerplant_gas_electricity_1) +<= 0 + +c_u_InvestmentFlowBlock_max(powerplant_gas_electricity_1_3)_: ++1 flow(powerplant_gas_electricity_1_3) +-1 InvestmentFlowBlock_total(powerplant_gas_electricity_1) +<= 0 + +c_u_InvestmentFlowBlock_max(powerplant_gas_electricity_2_4)_: ++1 flow(powerplant_gas_electricity_2_4) +-1 InvestmentFlowBlock_total(powerplant_gas_electricity_2) +<= 0 + +c_u_InvestmentFlowBlock_max(powerplant_gas_electricity_2_5)_: ++1 flow(powerplant_gas_electricity_2_5) +-1 InvestmentFlowBlock_total(powerplant_gas_electricity_2) +<= 0 + +c_u_InvestmentFlowBlock_overall_maximum(powerplant_gas_electricity_0)_: ++1 InvestmentFlowBlock_total(powerplant_gas_electricity_0) +<= 10000 + +c_u_InvestmentFlowBlock_overall_maximum(powerplant_gas_electricity_1)_: ++1 InvestmentFlowBlock_total(powerplant_gas_electricity_1) +<= 10000 + +c_u_InvestmentFlowBlock_overall_maximum(powerplant_gas_electricity_2)_: ++1 InvestmentFlowBlock_total(powerplant_gas_electricity_2) +<= 10000 + +c_l_InvestmentFlowBlock_overall_minimum(powerplant_gas_electricity)_: ++1 InvestmentFlowBlock_total(powerplant_gas_electricity_2) +>= 200 + +bounds + 0 <= InvestmentFlowBlock_invest(powerplant_gas_electricity_0) <= 1000 + 0 <= InvestmentFlowBlock_invest(powerplant_gas_electricity_1) <= 1000 + 0 <= InvestmentFlowBlock_invest(powerplant_gas_electricity_2) <= 1000 + 0 <= flow(powerplant_gas_electricity_0_0) <= +inf + 0 <= flow(powerplant_gas_electricity_0_1) <= +inf + 0 <= flow(powerplant_gas_electricity_1_2) <= +inf + 0 <= flow(powerplant_gas_electricity_1_3) <= +inf + 0 <= flow(powerplant_gas_electricity_2_4) <= +inf + 0 <= flow(powerplant_gas_electricity_2_5) <= +inf + 0 <= flow(gas_powerplant_gas_0_0) <= +inf + 0 <= flow(gas_powerplant_gas_0_1) <= +inf + 0 <= flow(gas_powerplant_gas_1_2) <= +inf + 0 <= flow(gas_powerplant_gas_1_3) <= +inf + 0 <= flow(gas_powerplant_gas_2_4) <= +inf + 0 <= flow(gas_powerplant_gas_2_5) <= +inf + 0 <= InvestmentFlowBlock_total(powerplant_gas_electricity_0) <= +inf + 0 <= InvestmentFlowBlock_total(powerplant_gas_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_old(powerplant_gas_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_total(powerplant_gas_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_old(powerplant_gas_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(powerplant_gas_electricity_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(powerplant_gas_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(powerplant_gas_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(powerplant_gas_electricity_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(powerplant_gas_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(powerplant_gas_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_old(powerplant_gas_electricity_0) <= +inf +end diff --git a/tests/lp_files/storage_invest_1_multi_period_remaining_value.lp b/tests/lp_files/storage_invest_1_multi_period_remaining_value.lp new file mode 100644 index 000000000..674580183 --- /dev/null +++ b/tests/lp_files/storage_invest_1_multi_period_remaining_value.lp @@ -0,0 +1,505 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++56 flow(electricityBus_storage1_0_0) ++56 flow(electricityBus_storage1_0_1) ++54.90196078431372 flow(electricityBus_storage1_1_2) ++54.90196078431372 flow(electricityBus_storage1_1_3) ++53.82545174932718 flow(electricityBus_storage1_2_4) ++53.82545174932718 flow(electricityBus_storage1_2_5) ++24 flow(storage1_electricityBus_0_0) ++24 flow(storage1_electricityBus_0_1) ++23.52941176470588 flow(storage1_electricityBus_1_2) ++23.52941176470588 flow(storage1_electricityBus_1_3) ++23.06805074971165 flow(storage1_electricityBus_2_4) ++23.06805074971165 flow(storage1_electricityBus_2_5) ++3.415797742191323 GenericInvestmentStorageBlock_invest(storage1_0) ++4.881348776484851 GenericInvestmentStorageBlock_invest(storage1_1) ++8.44720668509319 GenericInvestmentStorageBlock_invest(storage1_2) + +s.t. + +c_e_BusBlock_balance(electricityBus_0_0)_: +-1 flow(electricityBus_storage1_0_0) ++1 flow(storage1_electricityBus_0_0) += 0 + +c_e_BusBlock_balance(electricityBus_0_1)_: +-1 flow(electricityBus_storage1_0_1) ++1 flow(storage1_electricityBus_0_1) += 0 + +c_e_BusBlock_balance(electricityBus_1_2)_: +-1 flow(electricityBus_storage1_1_2) ++1 flow(storage1_electricityBus_1_2) += 0 + +c_e_BusBlock_balance(electricityBus_1_3)_: +-1 flow(electricityBus_storage1_1_3) ++1 flow(storage1_electricityBus_1_3) += 0 + +c_e_BusBlock_balance(electricityBus_2_4)_: +-1 flow(electricityBus_storage1_2_4) ++1 flow(storage1_electricityBus_2_4) += 0 + +c_e_BusBlock_balance(electricityBus_2_5)_: +-1 flow(electricityBus_storage1_2_5) ++1 flow(storage1_electricityBus_2_5) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_0)_: ++1 InvestmentFlowBlock_total(storage1_electricityBus_0) +-1 InvestmentFlowBlock_invest(storage1_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_1)_: +-1 InvestmentFlowBlock_total(storage1_electricityBus_0) ++1 InvestmentFlowBlock_total(storage1_electricityBus_1) +-1 InvestmentFlowBlock_invest(storage1_electricityBus_1) ++1 InvestmentFlowBlock_old(storage1_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage1_electricityBus_2)_: +-1 InvestmentFlowBlock_total(storage1_electricityBus_1) ++1 InvestmentFlowBlock_total(storage1_electricityBus_2) +-1 InvestmentFlowBlock_invest(storage1_electricityBus_2) ++1 InvestmentFlowBlock_old(storage1_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_0)_: ++1 InvestmentFlowBlock_total(electricityBus_storage1_0) +-1 InvestmentFlowBlock_invest(electricityBus_storage1_0) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_1)_: +-1 InvestmentFlowBlock_total(electricityBus_storage1_0) ++1 InvestmentFlowBlock_total(electricityBus_storage1_1) +-1 InvestmentFlowBlock_invest(electricityBus_storage1_1) ++1 InvestmentFlowBlock_old(electricityBus_storage1_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage1_2)_: +-1 InvestmentFlowBlock_total(electricityBus_storage1_1) ++1 InvestmentFlowBlock_total(electricityBus_storage1_2) +-1 InvestmentFlowBlock_invest(electricityBus_storage1_2) ++1 InvestmentFlowBlock_old(electricityBus_storage1_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_0)_: ++1 InvestmentFlowBlock_old_end(storage1_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_1)_: ++1 InvestmentFlowBlock_old_end(storage1_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage1_electricityBus_2)_: ++1 InvestmentFlowBlock_old_end(storage1_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_0)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage1_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_1)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage1_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage1_2)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage1_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_0)_: ++1 InvestmentFlowBlock_old_exo(storage1_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_1)_: ++1 InvestmentFlowBlock_old_exo(storage1_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage1_electricityBus_2)_: ++1 InvestmentFlowBlock_old_exo(storage1_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_0)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage1_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_1)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage1_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage1_2)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage1_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_0)_: +-1 InvestmentFlowBlock_old_end(storage1_electricityBus_0) +-1 InvestmentFlowBlock_old_exo(storage1_electricityBus_0) ++1 InvestmentFlowBlock_old(storage1_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_1)_: ++1 InvestmentFlowBlock_old(storage1_electricityBus_1) +-1 InvestmentFlowBlock_old_end(storage1_electricityBus_1) +-1 InvestmentFlowBlock_old_exo(storage1_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage1_electricityBus_2)_: ++1 InvestmentFlowBlock_old(storage1_electricityBus_2) +-1 InvestmentFlowBlock_old_end(storage1_electricityBus_2) +-1 InvestmentFlowBlock_old_exo(storage1_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_0)_: +-1 InvestmentFlowBlock_old_end(electricityBus_storage1_0) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage1_0) ++1 InvestmentFlowBlock_old(electricityBus_storage1_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_1)_: ++1 InvestmentFlowBlock_old(electricityBus_storage1_1) +-1 InvestmentFlowBlock_old_end(electricityBus_storage1_1) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage1_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage1_2)_: ++1 InvestmentFlowBlock_old(electricityBus_storage1_2) +-1 InvestmentFlowBlock_old_end(electricityBus_storage1_2) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage1_2) += 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_0_0)_: ++1 flow(storage1_electricityBus_0_0) +-1 InvestmentFlowBlock_total(storage1_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_0_1)_: ++1 flow(storage1_electricityBus_0_1) +-1 InvestmentFlowBlock_total(storage1_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_1_2)_: ++1 flow(storage1_electricityBus_1_2) +-1 InvestmentFlowBlock_total(storage1_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_1_3)_: ++1 flow(storage1_electricityBus_1_3) +-1 InvestmentFlowBlock_total(storage1_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_2_4)_: ++1 flow(storage1_electricityBus_2_4) +-1 InvestmentFlowBlock_total(storage1_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage1_electricityBus_2_5)_: ++1 flow(storage1_electricityBus_2_5) +-1 InvestmentFlowBlock_total(storage1_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_0_0)_: ++1 flow(electricityBus_storage1_0_0) +-1 InvestmentFlowBlock_total(electricityBus_storage1_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_0_1)_: ++1 flow(electricityBus_storage1_0_1) +-1 InvestmentFlowBlock_total(electricityBus_storage1_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_1_2)_: ++1 flow(electricityBus_storage1_1_2) +-1 InvestmentFlowBlock_total(electricityBus_storage1_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_1_3)_: ++1 flow(electricityBus_storage1_1_3) +-1 InvestmentFlowBlock_total(electricityBus_storage1_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_2_4)_: ++1 flow(electricityBus_storage1_2_4) +-1 InvestmentFlowBlock_total(electricityBus_storage1_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage1_2_5)_: ++1 flow(electricityBus_storage1_2_5) +-1 InvestmentFlowBlock_total(electricityBus_storage1_2) +<= 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage1_0)_: +-1 GenericInvestmentStorageBlock_invest(storage1_0) ++1 GenericInvestmentStorageBlock_total(storage1_0) += 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage1_1)_: +-1 GenericInvestmentStorageBlock_invest(storage1_1) +-1 GenericInvestmentStorageBlock_total(storage1_0) ++1 GenericInvestmentStorageBlock_total(storage1_1) ++1 GenericInvestmentStorageBlock_old(storage1_1) += 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage1_2)_: +-1 GenericInvestmentStorageBlock_invest(storage1_2) +-1 GenericInvestmentStorageBlock_total(storage1_1) ++1 GenericInvestmentStorageBlock_total(storage1_2) ++1 GenericInvestmentStorageBlock_old(storage1_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage1_0)_: ++1 GenericInvestmentStorageBlock_old_end(storage1_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage1_1)_: ++1 GenericInvestmentStorageBlock_old_end(storage1_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage1_2)_: ++1 GenericInvestmentStorageBlock_old_end(storage1_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage1_0)_: ++1 GenericInvestmentStorageBlock_old_exo(storage1_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage1_1)_: ++1 GenericInvestmentStorageBlock_old_exo(storage1_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage1_2)_: ++1 GenericInvestmentStorageBlock_old_exo(storage1_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage1_0)_: +-1 GenericInvestmentStorageBlock_old_end(storage1_0) +-1 GenericInvestmentStorageBlock_old_exo(storage1_0) ++1 GenericInvestmentStorageBlock_old(storage1_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage1_1)_: ++1 GenericInvestmentStorageBlock_old(storage1_1) +-1 GenericInvestmentStorageBlock_old_end(storage1_1) +-1 GenericInvestmentStorageBlock_old_exo(storage1_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage1_2)_: ++1 GenericInvestmentStorageBlock_old(storage1_2) +-1 GenericInvestmentStorageBlock_old_end(storage1_2) +-1 GenericInvestmentStorageBlock_old_exo(storage1_2) += 0 + +c_e_GenericInvestmentStorageBlock_initially_empty(storage1_0)_: ++1 GenericInvestmentStorageBlock_storage_content(storage1_0) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage1_0_1)_: +-0.97 flow(electricityBus_storage1_0_1) ++1.1627906976744187 flow(storage1_electricityBus_0_1) +-0.87 GenericInvestmentStorageBlock_storage_content(storage1_0) ++1 GenericInvestmentStorageBlock_storage_content(storage1_1) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage1_1_2)_: +-0.97 flow(electricityBus_storage1_1_2) ++1.1627906976744187 flow(storage1_electricityBus_1_2) +-0.87 GenericInvestmentStorageBlock_storage_content(storage1_1) ++1 GenericInvestmentStorageBlock_storage_content(storage1_2) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage1_1_3)_: +-0.97 flow(electricityBus_storage1_1_3) ++1.1627906976744187 flow(storage1_electricityBus_1_3) +-0.87 GenericInvestmentStorageBlock_storage_content(storage1_2) ++1 GenericInvestmentStorageBlock_storage_content(storage1_3) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage1_2_4)_: +-0.97 flow(electricityBus_storage1_2_4) ++1.1627906976744187 flow(storage1_electricityBus_2_4) +-0.87 GenericInvestmentStorageBlock_storage_content(storage1_3) ++1 GenericInvestmentStorageBlock_storage_content(storage1_4) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage1_2_5)_: +-0.97 flow(electricityBus_storage1_2_5) ++1.1627906976744187 flow(storage1_electricityBus_2_5) +-0.87 GenericInvestmentStorageBlock_storage_content(storage1_4) ++1 GenericInvestmentStorageBlock_storage_content(storage1_5) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage1_0)_: ++1 InvestmentFlowBlock_total(electricityBus_storage1_0) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage1_0) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage1_1)_: ++1 InvestmentFlowBlock_total(electricityBus_storage1_1) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage1_1) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage1_2)_: ++1 InvestmentFlowBlock_total(electricityBus_storage1_2) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage1_2) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage1_0)_: ++1 InvestmentFlowBlock_total(storage1_electricityBus_0) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage1_0) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage1_1)_: ++1 InvestmentFlowBlock_total(storage1_electricityBus_1) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage1_1) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage1_2)_: ++1 InvestmentFlowBlock_total(storage1_electricityBus_2) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage1_2) += 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage1_0_0)_: +-0.9 GenericInvestmentStorageBlock_total(storage1_0) ++1 GenericInvestmentStorageBlock_storage_content(storage1_0) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage1_0_1)_: +-0.9 GenericInvestmentStorageBlock_total(storage1_0) ++1 GenericInvestmentStorageBlock_storage_content(storage1_1) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage1_1_2)_: +-0.9 GenericInvestmentStorageBlock_total(storage1_1) ++1 GenericInvestmentStorageBlock_storage_content(storage1_2) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage1_1_3)_: +-0.9 GenericInvestmentStorageBlock_total(storage1_1) ++1 GenericInvestmentStorageBlock_storage_content(storage1_3) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage1_2_4)_: +-0.9 GenericInvestmentStorageBlock_total(storage1_2) ++1 GenericInvestmentStorageBlock_storage_content(storage1_4) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage1_2_5)_: +-0.9 GenericInvestmentStorageBlock_total(storage1_2) ++1 GenericInvestmentStorageBlock_storage_content(storage1_5) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage1_0_0)_: ++0.1 GenericInvestmentStorageBlock_total(storage1_0) +-1 GenericInvestmentStorageBlock_storage_content(storage1_0) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage1_0_1)_: ++0.1 GenericInvestmentStorageBlock_total(storage1_0) +-1 GenericInvestmentStorageBlock_storage_content(storage1_1) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage1_1_2)_: ++0.1 GenericInvestmentStorageBlock_total(storage1_1) +-1 GenericInvestmentStorageBlock_storage_content(storage1_2) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage1_1_3)_: ++0.1 GenericInvestmentStorageBlock_total(storage1_1) +-1 GenericInvestmentStorageBlock_storage_content(storage1_3) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage1_2_4)_: ++0.1 GenericInvestmentStorageBlock_total(storage1_2) +-1 GenericInvestmentStorageBlock_storage_content(storage1_4) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage1_2_5)_: ++0.1 GenericInvestmentStorageBlock_total(storage1_2) +-1 GenericInvestmentStorageBlock_storage_content(storage1_5) +<= 0 + +c_u_GenericInvestmentStorageBlock_overall_storage_maximum(storage1_0)_: ++1 GenericInvestmentStorageBlock_total(storage1_0) +<= 1000 + +c_u_GenericInvestmentStorageBlock_overall_storage_maximum(storage1_1)_: ++1 GenericInvestmentStorageBlock_total(storage1_1) +<= 1000 + +c_u_GenericInvestmentStorageBlock_overall_storage_maximum(storage1_2)_: ++1 GenericInvestmentStorageBlock_total(storage1_2) +<= 1000 + +c_l_GenericInvestmentStorageBlock_overall_minimum(storage1)_: ++1 GenericInvestmentStorageBlock_total(storage1_2) +>= 2 + +bounds + 0 <= flow(electricityBus_storage1_0_0) <= +inf + 0 <= flow(electricityBus_storage1_0_1) <= +inf + 0 <= flow(electricityBus_storage1_1_2) <= +inf + 0 <= flow(electricityBus_storage1_1_3) <= +inf + 0 <= flow(electricityBus_storage1_2_4) <= +inf + 0 <= flow(electricityBus_storage1_2_5) <= +inf + 0 <= flow(storage1_electricityBus_0_0) <= +inf + 0 <= flow(storage1_electricityBus_0_1) <= +inf + 0 <= flow(storage1_electricityBus_1_2) <= +inf + 0 <= flow(storage1_electricityBus_1_3) <= +inf + 0 <= flow(storage1_electricityBus_2_4) <= +inf + 0 <= flow(storage1_electricityBus_2_5) <= +inf + 0 <= GenericInvestmentStorageBlock_invest(storage1_0) <= 234 + 0 <= GenericInvestmentStorageBlock_invest(storage1_1) <= 234 + 0 <= GenericInvestmentStorageBlock_invest(storage1_2) <= 234 + 0 <= InvestmentFlowBlock_total(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_total(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_total(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_invest(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage1_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage1_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage1_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage1_0) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage1_0) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage1_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage1_1) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage1_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage1_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage1_0) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage1_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage1_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage1_0) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage1_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage1_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage1_0) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage1_0) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage1_1) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage1_2) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage1_3) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage1_4) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage1_5) <= +inf +end diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index 2696f5ace..4d4fa1700 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -147,6 +147,39 @@ def test_linear_converter_invest(self): self.energysystem.add(bgas, bel, converter) self.compare_lp_files("linear_converter_invest_multi_period.lp") + def test_linear_converter_invest_remaining_value(self): + """Constraint test of a Converter with Investment.""" + + bgas = solph.buses.Bus(label="gas") + + bel = solph.buses.Bus(label="electricity") + + converter = solph.components.Converter( + label="powerplant_gas", + inputs={bgas: solph.flows.Flow()}, + outputs={ + bel: solph.flows.Flow( + variable_costs=50, + investment=solph.Investment( + existing=50, + maximum=1000, + overall_maximum=10000, + overall_minimum=200, + ep_costs=[20, 19, 18], + age=5, + lifetime=40, + ), + ) + }, + conversion_factors={bel: 0.58}, + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(bgas, bel, converter) + self.compare_lp_files( + "linear_converter_invest_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_linear_converter_invest_old_capacity(self): """Constraint test of a Converter with Investment.""" @@ -365,6 +398,42 @@ def test_storage_invest_1(self): self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_1_multi_period.lp") + def test_storage_invest_1_remaining_value(self): + """All invest variables are coupled. The invest variables of the Flows + will be created during the initialisation of the storage e.g. battery + """ + bel = solph.buses.Bus(label="electricityBus") + + storage = solph.components.GenericStorage( + label="storage1", + inputs={bel: solph.flows.Flow(variable_costs=56)}, + outputs={bel: solph.flows.Flow(variable_costs=24)}, + nominal_storage_capacity=None, + loss_rate=0.13, + max_storage_level=0.9, + min_storage_level=0.1, + invest_relation_input_capacity=1 / 6, + invest_relation_output_capacity=1 / 6, + lifetime_inflow=20, + lifetime_outflow=20, + inflow_conversion_factor=0.97, + outflow_conversion_factor=0.86, + investment=solph.Investment( + ep_costs=[145, 130, 115], + maximum=234, + lifetime=20, + interest_rate=0.05, + overall_maximum=1000, + overall_minimum=2, + ), + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(bel, storage) + self.compare_lp_files( + "storage_invest_1_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_storage_invest_2(self): """All can be free extended to their own cost.""" bel = solph.buses.Bus(label="electricityBus") @@ -1631,6 +1700,44 @@ def test_dsm_module_DIW_invest(self): self.energysystem.add(b_elec, sinkdsm) self.compare_lp_files("dsm_module_DIW_invest_multi_period.lp") + def test_dsm_module_DIW_invest_remaining_value(self): + """Constraint test of SinkDSM with approach=DLR and investments""" + + b_elec = solph.buses.Bus(label="bus_elec") + sinkdsm = solph.components.experimental.SinkDSM( + label="demand_dsm", + inputs={b_elec: solph.flows.Flow()}, + demand=[1] * 6, + capacity_up=[0.5] * 6, + capacity_down=[0.5] * 6, + approach="DIW", + max_demand=[1, 2, 3], + delay_time=1, + cost_dsm_down_shift=1, + cost_dsm_up=1, + cost_dsm_down_shed=100, + shed_eligibility=True, + recovery_time_shed=2, + shed_time=2, + investment=solph.Investment( + ep_costs=[100, 90, 80], + existing=50, + minimum=33, + maximum=100, + age=1, + lifetime=20, + fixed_costs=20, + overall_maximum=1000, + overall_minimum=5, + ), + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(b_elec, sinkdsm) + self.compare_lp_files( + "dsm_module_DIW_invest_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_dsm_module_DLR_invest(self): """Constraint test of SinkDSM with approach=DLR and investments""" @@ -1667,6 +1774,46 @@ def test_dsm_module_DLR_invest(self): self.energysystem.add(b_elec, sinkdsm) self.compare_lp_files("dsm_module_DLR_invest_multi_period.lp") + def test_dsm_module_DLR_invest_remaining_value(self): + """Constraint test of SinkDSM with approach=DLR and investments""" + + b_elec = solph.buses.Bus(label="bus_elec") + sinkdsm = solph.components.experimental.SinkDSM( + label="demand_dsm", + inputs={b_elec: solph.flows.Flow()}, + demand=[1] * 6, + capacity_up=[0.5] * 6, + capacity_down=[0.5] * 6, + approach="DLR", + max_demand=[1, 2, 3], + delay_time=2, + shift_time=1, + cost_dsm_down_shift=1, + cost_dsm_up=1, + cost_dsm_down_shed=100, + shed_eligibility=True, + recovery_time_shed=2, + shed_time=2, + n_yearLimit_shed=50, + investment=solph.Investment( + ep_costs=[100, 90, 80], + existing=50, + minimum=33, + maximum=100, + age=1, + lifetime=20, + fixed_costs=20, + overall_maximum=1000, + overall_minimum=5, + ), + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(b_elec, sinkdsm) + self.compare_lp_files( + "dsm_module_DLR_invest_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_dsm_module_oemof_invest(self): """Constraint test of SinkDSM with approach=oemof and investments""" @@ -1701,6 +1848,44 @@ def test_dsm_module_oemof_invest(self): self.energysystem.add(b_elec, sinkdsm) self.compare_lp_files("dsm_module_oemof_invest_multi_period.lp") + def test_dsm_module_oemof_invest_remaining_value(self): + """Constraint test of SinkDSM with approach=oemof and investments""" + + b_elec = solph.buses.Bus(label="bus_elec") + sinkdsm = solph.components.experimental.SinkDSM( + label="demand_dsm", + inputs={b_elec: solph.flows.Flow()}, + demand=[1] * 6, + capacity_up=[0.5, 0.4, 0.5, 0.3, 0.3, 0.3], + capacity_down=[0.5, 0.4, 0.5, 0.3, 0.3, 0.3], + approach="oemof", + max_demand=[1, 2, 3], + shift_interval=2, + cost_dsm_down_shift=1, + cost_dsm_up=1, + cost_dsm_down_shed=100, + shed_eligibility=True, + recovery_time_shed=2, + shed_time=2, + investment=solph.Investment( + ep_costs=[100, 90, 80], + existing=50, + minimum=33, + maximum=100, + age=1, + lifetime=20, + fixed_costs=20, + overall_maximum=1000, + overall_minimum=5, + ), + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(b_elec, sinkdsm) + self.compare_lp_files( + "dsm_module_oemof_invest_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_nonconvex_investment_storage_without_offset(self): """All invest variables are coupled. The invest variables of the Flows will be created during the initialisation of the storage e.g. battery From ceba43dce89d638cda65175b9764c167f62ba824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 13 Oct 2023 17:06:30 +0200 Subject: [PATCH 077/180] Delete tangling white space in docs --- docs/usage.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index fe60ea434..6f8373798 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -643,8 +643,8 @@ The following example pictures a Pumped Hydroelectric Energy Storage (PHES). Bot solph.components.GenericStorage( label='PHES', - inputs={b_el: solph.flows.Flow(nominal_value= solph.Investment(ep_costs=500))}, - outputs={b_el: solph.flows.Flow(nominal_value= solph.Investment(ep_costs=500)}, + inputs={b_el: solph.flows.Flow(nominal_value=solph.Investment(ep_costs=500))}, + outputs={b_el: solph.flows.Flow(nominal_value=solph.Investment(ep_costs=500)}, loss_rate=0.001, inflow_conversion_factor=0.98, outflow_conversion_factor=0.8), investment = solph.Investment(ep_costs=40)) From 723a77a1c001beeb2684e817392ad8a31bbf7749 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 17:13:57 +0200 Subject: [PATCH 078/180] Add minor corrections in docs --- docs/usage.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index a160a6c83..1f7b6f82b 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1270,11 +1270,11 @@ Besides the `invest` variable, new variables are introduced as well. These are: has not yet been tested. * For now, both, the `timeindex` as well as the `timeincrement` of an energy system have to be defined since they have to be of the same length for a multi-period model. - * You can choose whether or not to re-evaluate assets at the end of the optimization horizon. If you set attribute + * You can choose whether to re-evaluate assets at the end of the optimization horizon. If you set attribute `use_remaining_value` of the energy system to True (defaults to False), this leads to the model evaluating the - different in value at the end of the optimization horizon vs. at the time the investment was made. The difference - in value is added to or subtracted from the respective investment costs increment, assuming assets are to be - liquidated / re-evaluated at the end of the optimization horizon. + difference in the asset value at the end of the optimization horizon vs. at the time the investment was made. + The difference in value is added to or subtracted from the respective investment costs increment, + assuming assets are to be liquidated / re-evaluated at the end of the optimization horizon. * Also please be aware, that periods correspond to years by default. You could also choose monthly periods, but you would need to be very careful in parameterizing your energy system and your model and also, this would mean monthly discounting (if applicable) as well as specifying your plants lifetimes in months. From c1b4bffdcaf0e551dd6f787c67294098dd44a5b7 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 13 Oct 2023 17:20:59 +0200 Subject: [PATCH 079/180] Add nonconvex investment tests to prevent coverage decrease --- ...ith_offset_multi_period_remaining_value.lp | 206 +++++++ ...out_offset_multi_period_remaining_value.lp | 203 +++++++ ...ith_offset_multi_period_remaining_value.lp | 529 ++++++++++++++++++ ...out_offset_multi_period_remaining_value.lp | 526 +++++++++++++++++ tests/multi_period_constraint_tests.py | 128 +++++ 5 files changed, 1592 insertions(+) create mode 100644 tests/lp_files/flow_invest_with_offset_multi_period_remaining_value.lp create mode 100644 tests/lp_files/flow_invest_without_offset_multi_period_remaining_value.lp create mode 100644 tests/lp_files/storage_invest_with_offset_multi_period_remaining_value.lp create mode 100644 tests/lp_files/storage_invest_without_offset_multi_period_remaining_value.lp diff --git a/tests/lp_files/flow_invest_with_offset_multi_period_remaining_value.lp b/tests/lp_files/flow_invest_with_offset_multi_period_remaining_value.lp new file mode 100644 index 000000000..5e4510206 --- /dev/null +++ b/tests/lp_files/flow_invest_with_offset_multi_period_remaining_value.lp @@ -0,0 +1,206 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++88.1844182057801 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) ++34 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_0) ++58.20563481102971 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) ++33.33333333333333 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_1) ++28.814670698529593 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) ++32.6797385620915 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_2) ++25 flow(source_nonconvex_invest_electricityBus_0_0) ++25 flow(source_nonconvex_invest_electricityBus_0_1) ++24.509803921568626 flow(source_nonconvex_invest_electricityBus_1_2) ++24.509803921568626 flow(source_nonconvex_invest_electricityBus_1_3) ++24.029219530949632 flow(source_nonconvex_invest_electricityBus_2_4) ++24.029219530949632 flow(source_nonconvex_invest_electricityBus_2_5) + +s.t. + +c_e_BusBlock_balance(electricityBus_0_0)_: ++1 flow(source_nonconvex_invest_electricityBus_0_0) += 0 + +c_e_BusBlock_balance(electricityBus_0_1)_: ++1 flow(source_nonconvex_invest_electricityBus_0_1) += 0 + +c_e_BusBlock_balance(electricityBus_1_2)_: ++1 flow(source_nonconvex_invest_electricityBus_1_2) += 0 + +c_e_BusBlock_balance(electricityBus_1_3)_: ++1 flow(source_nonconvex_invest_electricityBus_1_3) += 0 + +c_e_BusBlock_balance(electricityBus_2_4)_: ++1 flow(source_nonconvex_invest_electricityBus_2_4) += 0 + +c_e_BusBlock_balance(electricityBus_2_5)_: ++1 flow(source_nonconvex_invest_electricityBus_2_5) += 0 + +c_u_InvestmentFlowBlock_minimum_rule(source_nonconvex_invest_electricityBus_0)_: +-1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) ++15 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_minimum_rule(source_nonconvex_invest_electricityBus_1)_: +-1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) ++15 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_minimum_rule(source_nonconvex_invest_electricityBus_2)_: +-1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) ++15 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_maximum_rule(source_nonconvex_invest_electricityBus_0)_: ++1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) +-20 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_maximum_rule(source_nonconvex_invest_electricityBus_1)_: ++1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) +-20 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_maximum_rule(source_nonconvex_invest_electricityBus_2)_: ++1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) +-20 InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_2) +<= 0 + +c_e_InvestmentFlowBlock_total_rule(source_nonconvex_invest_electricityBus_0)_: +-1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) ++1 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_total_rule(source_nonconvex_invest_electricityBus_1)_: +-1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) +-1 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_0) ++1 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_1) ++1 InvestmentFlowBlock_old(source_nonconvex_invest_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(source_nonconvex_invest_electricityBus_2)_: +-1 InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) +-1 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_1) ++1 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_2) ++1 InvestmentFlowBlock_old(source_nonconvex_invest_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(source_nonconvex_invest_electricityBus_0)_: ++1 InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(source_nonconvex_invest_electricityBus_1)_: ++1 InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(source_nonconvex_invest_electricityBus_2)_: ++1 InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(source_nonconvex_invest_electricityBus_0)_: ++1 InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(source_nonconvex_invest_electricityBus_1)_: ++1 InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(source_nonconvex_invest_electricityBus_2)_: ++1 InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(source_nonconvex_invest_electricityBus_0)_: +-1 InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_0) +-1 InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_0) ++1 InvestmentFlowBlock_old(source_nonconvex_invest_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(source_nonconvex_invest_electricityBus_1)_: ++1 InvestmentFlowBlock_old(source_nonconvex_invest_electricityBus_1) +-1 InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_1) +-1 InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(source_nonconvex_invest_electricityBus_2)_: ++1 InvestmentFlowBlock_old(source_nonconvex_invest_electricityBus_2) +-1 InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_2) +-1 InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_2) += 0 + +c_u_InvestmentFlowBlock_max(source_nonconvex_invest_electricityBus_0_0)_: ++1 flow(source_nonconvex_invest_electricityBus_0_0) +-0.8 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(source_nonconvex_invest_electricityBus_0_1)_: ++1 flow(source_nonconvex_invest_electricityBus_0_1) +-0.8 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(source_nonconvex_invest_electricityBus_1_2)_: ++1 flow(source_nonconvex_invest_electricityBus_1_2) +-0.8 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(source_nonconvex_invest_electricityBus_1_3)_: ++1 flow(source_nonconvex_invest_electricityBus_1_3) +-0.8 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(source_nonconvex_invest_electricityBus_2_4)_: ++1 flow(source_nonconvex_invest_electricityBus_2_4) +-0.8 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(source_nonconvex_invest_electricityBus_2_5)_: ++1 flow(source_nonconvex_invest_electricityBus_2_5) +-0.8 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_full_load_time_max(source_nonconvex_invest_electricityBus)_: ++1 flow(source_nonconvex_invest_electricityBus_0_0) ++1 flow(source_nonconvex_invest_electricityBus_0_1) ++1 flow(source_nonconvex_invest_electricityBus_1_2) ++1 flow(source_nonconvex_invest_electricityBus_1_3) ++1 flow(source_nonconvex_invest_electricityBus_2_4) ++1 flow(source_nonconvex_invest_electricityBus_2_5) +-2.3 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_0) +-2.3 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_1) +-2.3 InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_2) +<= 0.0 + +bounds + 0 <= InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_0) <= 20 + 0 <= InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_0) <= 1 + 0 <= InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_1) <= 20 + 0 <= InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_1) <= 1 + 0 <= InvestmentFlowBlock_invest(source_nonconvex_invest_electricityBus_2) <= 20 + 0 <= InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_2) <= 1 + 0 <= flow(source_nonconvex_invest_electricityBus_0_0) <= +inf + 0 <= flow(source_nonconvex_invest_electricityBus_0_1) <= +inf + 0 <= flow(source_nonconvex_invest_electricityBus_1_2) <= +inf + 0 <= flow(source_nonconvex_invest_electricityBus_1_3) <= +inf + 0 <= flow(source_nonconvex_invest_electricityBus_2_4) <= +inf + 0 <= flow(source_nonconvex_invest_electricityBus_2_5) <= +inf + 0 <= InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old(source_nonconvex_invest_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_total(source_nonconvex_invest_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old(source_nonconvex_invest_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(source_nonconvex_invest_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(source_nonconvex_invest_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old(source_nonconvex_invest_electricityBus_0) <= +inf +binary + InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_0) + InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_1) + InvestmentFlowBlock_invest_status(source_nonconvex_invest_electricityBus_2) +end diff --git a/tests/lp_files/flow_invest_without_offset_multi_period_remaining_value.lp b/tests/lp_files/flow_invest_without_offset_multi_period_remaining_value.lp new file mode 100644 index 000000000..40b7e34a1 --- /dev/null +++ b/tests/lp_files/flow_invest_without_offset_multi_period_remaining_value.lp @@ -0,0 +1,203 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++88.1844182057801 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_0) ++58.20563481102971 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_1) ++28.814670698529593 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_2) ++25 flow(electricityBus_sink_nonconvex_invest_0_0) ++25 flow(electricityBus_sink_nonconvex_invest_0_1) ++24.509803921568626 flow(electricityBus_sink_nonconvex_invest_1_2) ++24.509803921568626 flow(electricityBus_sink_nonconvex_invest_1_3) ++24.029219530949632 flow(electricityBus_sink_nonconvex_invest_2_4) ++24.029219530949632 flow(electricityBus_sink_nonconvex_invest_2_5) + +s.t. + +c_e_BusBlock_balance(electricityBus_0_0)_: ++1 flow(electricityBus_sink_nonconvex_invest_0_0) += 0 + +c_e_BusBlock_balance(electricityBus_0_1)_: ++1 flow(electricityBus_sink_nonconvex_invest_0_1) += 0 + +c_e_BusBlock_balance(electricityBus_1_2)_: ++1 flow(electricityBus_sink_nonconvex_invest_1_2) += 0 + +c_e_BusBlock_balance(electricityBus_1_3)_: ++1 flow(electricityBus_sink_nonconvex_invest_1_3) += 0 + +c_e_BusBlock_balance(electricityBus_2_4)_: ++1 flow(electricityBus_sink_nonconvex_invest_2_4) += 0 + +c_e_BusBlock_balance(electricityBus_2_5)_: ++1 flow(electricityBus_sink_nonconvex_invest_2_5) += 0 + +c_u_InvestmentFlowBlock_minimum_rule(electricityBus_sink_nonconvex_invest_0)_: +-1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_0) ++15 InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_0) +<= 0 + +c_u_InvestmentFlowBlock_minimum_rule(electricityBus_sink_nonconvex_invest_1)_: +-1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_1) ++15 InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_1) +<= 0 + +c_u_InvestmentFlowBlock_minimum_rule(electricityBus_sink_nonconvex_invest_2)_: +-1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_2) ++15 InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_2) +<= 0 + +c_u_InvestmentFlowBlock_maximum_rule(electricityBus_sink_nonconvex_invest_0)_: ++1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_0) +-172 InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_0) +<= 0 + +c_u_InvestmentFlowBlock_maximum_rule(electricityBus_sink_nonconvex_invest_1)_: ++1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_1) +-172 InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_1) +<= 0 + +c_u_InvestmentFlowBlock_maximum_rule(electricityBus_sink_nonconvex_invest_2)_: ++1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_2) +-172 InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_2) +<= 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_sink_nonconvex_invest_0)_: +-1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_0) ++1 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_0) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_sink_nonconvex_invest_1)_: +-1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_1) +-1 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_0) ++1 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_1) ++1 InvestmentFlowBlock_old(electricityBus_sink_nonconvex_invest_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_sink_nonconvex_invest_2)_: +-1 InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_2) +-1 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_1) ++1 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_2) ++1 InvestmentFlowBlock_old(electricityBus_sink_nonconvex_invest_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_sink_nonconvex_invest_0)_: ++1 InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_sink_nonconvex_invest_1)_: ++1 InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_sink_nonconvex_invest_2)_: ++1 InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_sink_nonconvex_invest_0)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_sink_nonconvex_invest_1)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_sink_nonconvex_invest_2)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_sink_nonconvex_invest_0)_: +-1 InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_0) +-1 InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_0) ++1 InvestmentFlowBlock_old(electricityBus_sink_nonconvex_invest_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_sink_nonconvex_invest_1)_: ++1 InvestmentFlowBlock_old(electricityBus_sink_nonconvex_invest_1) +-1 InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_1) +-1 InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_sink_nonconvex_invest_2)_: ++1 InvestmentFlowBlock_old(electricityBus_sink_nonconvex_invest_2) +-1 InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_2) +-1 InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_2) += 0 + +c_u_InvestmentFlowBlock_max(electricityBus_sink_nonconvex_invest_0_0)_: ++1 flow(electricityBus_sink_nonconvex_invest_0_0) +-0.8 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_sink_nonconvex_invest_0_1)_: ++1 flow(electricityBus_sink_nonconvex_invest_0_1) +-0.8 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_sink_nonconvex_invest_1_2)_: ++1 flow(electricityBus_sink_nonconvex_invest_1_2) +-0.8 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_sink_nonconvex_invest_1_3)_: ++1 flow(electricityBus_sink_nonconvex_invest_1_3) +-0.8 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_sink_nonconvex_invest_2_4)_: ++1 flow(electricityBus_sink_nonconvex_invest_2_4) +-0.8 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_sink_nonconvex_invest_2_5)_: ++1 flow(electricityBus_sink_nonconvex_invest_2_5) +-0.8 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_2) +<= 0 + +c_u_InvestmentFlowBlock_full_load_time_max(electricityBus_sink_nonconvex_invest)_: ++1 flow(electricityBus_sink_nonconvex_invest_0_0) ++1 flow(electricityBus_sink_nonconvex_invest_0_1) ++1 flow(electricityBus_sink_nonconvex_invest_1_2) ++1 flow(electricityBus_sink_nonconvex_invest_1_3) ++1 flow(electricityBus_sink_nonconvex_invest_2_4) ++1 flow(electricityBus_sink_nonconvex_invest_2_5) +-2.3 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_0) +-2.3 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_1) +-2.3 InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_2) +<= 0.0 + +bounds + 0 <= InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_0) <= 172 + 0 <= InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_1) <= 172 + 0 <= InvestmentFlowBlock_invest(electricityBus_sink_nonconvex_invest_2) <= 172 + 0 <= flow(electricityBus_sink_nonconvex_invest_0_0) <= +inf + 0 <= flow(electricityBus_sink_nonconvex_invest_0_1) <= +inf + 0 <= flow(electricityBus_sink_nonconvex_invest_1_2) <= +inf + 0 <= flow(electricityBus_sink_nonconvex_invest_1_3) <= +inf + 0 <= flow(electricityBus_sink_nonconvex_invest_2_4) <= +inf + 0 <= flow(electricityBus_sink_nonconvex_invest_2_5) <= +inf + 0 <= InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_0) <= 1 + 0 <= InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_1) <= 1 + 0 <= InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_2) <= 1 + 0 <= InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_0) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_1) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_sink_nonconvex_invest_1) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_sink_nonconvex_invest_2) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_sink_nonconvex_invest_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_sink_nonconvex_invest_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_sink_nonconvex_invest_2) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_sink_nonconvex_invest_0) <= +inf +binary + InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_0) + InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_1) + InvestmentFlowBlock_invest_status(electricityBus_sink_nonconvex_invest_2) +end diff --git a/tests/lp_files/storage_invest_with_offset_multi_period_remaining_value.lp b/tests/lp_files/storage_invest_with_offset_multi_period_remaining_value.lp new file mode 100644 index 000000000..9347789d9 --- /dev/null +++ b/tests/lp_files/storage_invest_with_offset_multi_period_remaining_value.lp @@ -0,0 +1,529 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++56 flow(electricityBus_storage_non_convex_0_0) ++56 flow(electricityBus_storage_non_convex_0_1) ++54.90196078431372 flow(electricityBus_storage_non_convex_1_2) ++54.90196078431372 flow(electricityBus_storage_non_convex_1_3) ++53.82545174932718 flow(electricityBus_storage_non_convex_2_4) ++53.82545174932718 flow(electricityBus_storage_non_convex_2_5) ++24 flow(storage_non_convex_electricityBus_0_0) ++24 flow(storage_non_convex_electricityBus_0_1) ++23.52941176470588 flow(storage_non_convex_electricityBus_1_2) ++23.52941176470588 flow(storage_non_convex_electricityBus_1_3) ++23.06805074971165 flow(storage_non_convex_electricityBus_2_4) ++23.06805074971165 flow(storage_non_convex_electricityBus_2_5) ++25.57348127967623 GenericInvestmentStorageBlock_invest(storage_non_convex_0) ++5 GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) ++16.879634095198618 GenericInvestmentStorageBlock_invest(storage_non_convex_1) ++4.901960784313725 GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) ++8.35625450257358 GenericInvestmentStorageBlock_invest(storage_non_convex_2) ++4.805843906189927 GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) + +s.t. + +c_e_BusBlock_balance(electricityBus_0_0)_: +-1 flow(electricityBus_storage_non_convex_0_0) ++1 flow(storage_non_convex_electricityBus_0_0) += 0 + +c_e_BusBlock_balance(electricityBus_0_1)_: +-1 flow(electricityBus_storage_non_convex_0_1) ++1 flow(storage_non_convex_electricityBus_0_1) += 0 + +c_e_BusBlock_balance(electricityBus_1_2)_: +-1 flow(electricityBus_storage_non_convex_1_2) ++1 flow(storage_non_convex_electricityBus_1_2) += 0 + +c_e_BusBlock_balance(electricityBus_1_3)_: +-1 flow(electricityBus_storage_non_convex_1_3) ++1 flow(storage_non_convex_electricityBus_1_3) += 0 + +c_e_BusBlock_balance(electricityBus_2_4)_: +-1 flow(electricityBus_storage_non_convex_2_4) ++1 flow(storage_non_convex_electricityBus_2_4) += 0 + +c_e_BusBlock_balance(electricityBus_2_5)_: +-1 flow(electricityBus_storage_non_convex_2_5) ++1 flow(storage_non_convex_electricityBus_2_5) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_1)_: +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_2)_: +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_0)_: ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) +-1 InvestmentFlowBlock_invest(electricityBus_storage_non_convex_0) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_1)_: +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) +-1 InvestmentFlowBlock_invest(electricityBus_storage_non_convex_1) ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_2)_: +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) +-1 InvestmentFlowBlock_invest(electricityBus_storage_non_convex_2) ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_0)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_1)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_2)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_0)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_1)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_2)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_0)_: +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_0)_: +-1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_0) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_0) ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_1)_: ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_1) +-1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_1) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_2)_: ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) +-1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) += 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_0)_: ++1 flow(storage_non_convex_electricityBus_0_0) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_1)_: ++1 flow(storage_non_convex_electricityBus_0_1) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_2)_: ++1 flow(storage_non_convex_electricityBus_1_2) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_3)_: ++1 flow(storage_non_convex_electricityBus_1_3) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_4)_: ++1 flow(storage_non_convex_electricityBus_2_4) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_5)_: ++1 flow(storage_non_convex_electricityBus_2_5) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_0_0)_: ++1 flow(electricityBus_storage_non_convex_0_0) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_0_1)_: ++1 flow(electricityBus_storage_non_convex_0_1) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_1_2)_: ++1 flow(electricityBus_storage_non_convex_1_2) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_1_3)_: ++1 flow(electricityBus_storage_non_convex_1_3) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_2_4)_: ++1 flow(electricityBus_storage_non_convex_2_4) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_2_5)_: ++1 flow(electricityBus_storage_non_convex_2_5) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) +<= 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_non_convex_0)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_total(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_non_convex_1)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_total(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_total(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_old(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_non_convex_2)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_total(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_total(storage_non_convex_2) ++1 GenericInvestmentStorageBlock_old(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage_non_convex_0)_: ++1 GenericInvestmentStorageBlock_old_end(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage_non_convex_1)_: ++1 GenericInvestmentStorageBlock_old_end(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage_non_convex_2)_: ++1 GenericInvestmentStorageBlock_old_end(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage_non_convex_0)_: ++1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage_non_convex_1)_: ++1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage_non_convex_2)_: ++1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage_non_convex_0)_: +-1 GenericInvestmentStorageBlock_old_end(storage_non_convex_0) +-1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_old(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage_non_convex_1)_: ++1 GenericInvestmentStorageBlock_old(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_old_end(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage_non_convex_2)_: ++1 GenericInvestmentStorageBlock_old(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_old_end(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_initially_empty(storage_non_convex_0)_: ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_0_1)_: +-0.97 flow(electricityBus_storage_non_convex_0_1) ++1.1627906976744187 flow(storage_non_convex_electricityBus_0_1) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_1_2)_: +-0.97 flow(electricityBus_storage_non_convex_1_2) ++1.1627906976744187 flow(storage_non_convex_electricityBus_1_2) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_1_3)_: +-0.97 flow(electricityBus_storage_non_convex_1_3) ++1.1627906976744187 flow(storage_non_convex_electricityBus_1_3) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_2_4)_: +-0.97 flow(electricityBus_storage_non_convex_2_4) ++1.1627906976744187 flow(storage_non_convex_electricityBus_2_4) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_2_5)_: +-0.97 flow(electricityBus_storage_non_convex_2_5) ++1.1627906976744187 flow(storage_non_convex_electricityBus_2_5) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_5) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage_non_convex_0)_: ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage_non_convex_1)_: ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage_non_convex_2)_: ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage_non_convex_0)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage_non_convex_1)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage_non_convex_2)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_2) += 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_0_0)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_0_1)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_1_2)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_1_3)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_2_4)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_2) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_2_5)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_2) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_5) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_0_0)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_0) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_0_1)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_0) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_1_2)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_1_3)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_2_4)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_2_5)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_5) +<= 0 + +c_l_GenericInvestmentStorageBlock_limit_max(storage_non_convex_0)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_0) ++1454 GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_max(storage_non_convex_1)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_1) ++1454 GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_max(storage_non_convex_2)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_2) ++1454 GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_min(storage_non_convex_0)_: ++1 GenericInvestmentStorageBlock_invest(storage_non_convex_0) +-19 GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_min(storage_non_convex_1)_: ++1 GenericInvestmentStorageBlock_invest(storage_non_convex_1) +-19 GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_min(storage_non_convex_2)_: ++1 GenericInvestmentStorageBlock_invest(storage_non_convex_2) +-19 GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) +>= 0 + +bounds + 0 <= flow(electricityBus_storage_non_convex_0_0) <= +inf + 0 <= flow(electricityBus_storage_non_convex_0_1) <= +inf + 0 <= flow(electricityBus_storage_non_convex_1_2) <= +inf + 0 <= flow(electricityBus_storage_non_convex_1_3) <= +inf + 0 <= flow(electricityBus_storage_non_convex_2_4) <= +inf + 0 <= flow(electricityBus_storage_non_convex_2_5) <= +inf + 0 <= flow(storage_non_convex_electricityBus_0_0) <= +inf + 0 <= flow(storage_non_convex_electricityBus_0_1) <= +inf + 0 <= flow(storage_non_convex_electricityBus_1_2) <= +inf + 0 <= flow(storage_non_convex_electricityBus_1_3) <= +inf + 0 <= flow(storage_non_convex_electricityBus_2_4) <= +inf + 0 <= flow(storage_non_convex_electricityBus_2_5) <= +inf + 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_0) <= 1454 + 0 <= GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) <= 1 + 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_1) <= 1454 + 0 <= GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) <= 1 + 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_2) <= 1454 + 0 <= GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) <= 1 + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_5) <= +inf +binary + GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) + GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) + GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) +end diff --git a/tests/lp_files/storage_invest_without_offset_multi_period_remaining_value.lp b/tests/lp_files/storage_invest_without_offset_multi_period_remaining_value.lp new file mode 100644 index 000000000..179c59847 --- /dev/null +++ b/tests/lp_files/storage_invest_without_offset_multi_period_remaining_value.lp @@ -0,0 +1,526 @@ +\* Source Pyomo model name=Model *\ + +min +objective: ++56 flow(electricityBus_storage_non_convex_0_0) ++56 flow(electricityBus_storage_non_convex_0_1) ++54.90196078431372 flow(electricityBus_storage_non_convex_1_2) ++54.90196078431372 flow(electricityBus_storage_non_convex_1_3) ++53.82545174932718 flow(electricityBus_storage_non_convex_2_4) ++53.82545174932718 flow(electricityBus_storage_non_convex_2_5) ++24 flow(storage_non_convex_electricityBus_0_0) ++24 flow(storage_non_convex_electricityBus_0_1) ++23.52941176470588 flow(storage_non_convex_electricityBus_1_2) ++23.52941176470588 flow(storage_non_convex_electricityBus_1_3) ++23.06805074971165 flow(storage_non_convex_electricityBus_2_4) ++23.06805074971165 flow(storage_non_convex_electricityBus_2_5) ++24.868005934029988 GenericInvestmentStorageBlock_invest(storage_non_convex_0) ++16.413989016710378 GenericInvestmentStorageBlock_invest(storage_non_convex_1) ++8.125737136985347 GenericInvestmentStorageBlock_invest(storage_non_convex_2) + +s.t. + +c_e_BusBlock_balance(electricityBus_0_0)_: +-1 flow(electricityBus_storage_non_convex_0_0) ++1 flow(storage_non_convex_electricityBus_0_0) += 0 + +c_e_BusBlock_balance(electricityBus_0_1)_: +-1 flow(electricityBus_storage_non_convex_0_1) ++1 flow(storage_non_convex_electricityBus_0_1) += 0 + +c_e_BusBlock_balance(electricityBus_1_2)_: +-1 flow(electricityBus_storage_non_convex_1_2) ++1 flow(storage_non_convex_electricityBus_1_2) += 0 + +c_e_BusBlock_balance(electricityBus_1_3)_: +-1 flow(electricityBus_storage_non_convex_1_3) ++1 flow(storage_non_convex_electricityBus_1_3) += 0 + +c_e_BusBlock_balance(electricityBus_2_4)_: +-1 flow(electricityBus_storage_non_convex_2_4) ++1 flow(storage_non_convex_electricityBus_2_4) += 0 + +c_e_BusBlock_balance(electricityBus_2_5)_: +-1 flow(electricityBus_storage_non_convex_2_5) ++1 flow(storage_non_convex_electricityBus_2_5) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_1)_: +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_non_convex_electricityBus_2)_: +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_0)_: ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) +-1 InvestmentFlowBlock_invest(electricityBus_storage_non_convex_0) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_1)_: +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) +-1 InvestmentFlowBlock_invest(electricityBus_storage_non_convex_1) ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_1) += 0 + +c_e_InvestmentFlowBlock_total_rule(electricityBus_storage_non_convex_2)_: +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) +-1 InvestmentFlowBlock_invest(electricityBus_storage_non_convex_2) ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_0)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_1)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_end(electricityBus_storage_non_convex_2)_: ++1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_0)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_0)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_0) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_1)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_1) += 0 + +c_e_InvestmentFlowBlock_old_rule_exo(electricityBus_storage_non_convex_2)_: ++1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_0)_: +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_1)_: ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(storage_non_convex_electricityBus_2)_: ++1 InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) +-1 InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_0)_: +-1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_0) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_0) ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_0) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_1)_: ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_1) +-1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_1) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_1) += 0 + +c_e_InvestmentFlowBlock_old_rule(electricityBus_storage_non_convex_2)_: ++1 InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) +-1 InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) +-1 InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) += 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_0)_: ++1 flow(storage_non_convex_electricityBus_0_0) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_0_1)_: ++1 flow(storage_non_convex_electricityBus_0_1) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_2)_: ++1 flow(storage_non_convex_electricityBus_1_2) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_1_3)_: ++1 flow(storage_non_convex_electricityBus_1_3) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_4)_: ++1 flow(storage_non_convex_electricityBus_2_4) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_non_convex_electricityBus_2_5)_: ++1 flow(storage_non_convex_electricityBus_2_5) +-1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_0_0)_: ++1 flow(electricityBus_storage_non_convex_0_0) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_0_1)_: ++1 flow(electricityBus_storage_non_convex_0_1) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_1_2)_: ++1 flow(electricityBus_storage_non_convex_1_2) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_1_3)_: ++1 flow(electricityBus_storage_non_convex_1_3) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_2_4)_: ++1 flow(electricityBus_storage_non_convex_2_4) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) +<= 0 + +c_u_InvestmentFlowBlock_max(electricityBus_storage_non_convex_2_5)_: ++1 flow(electricityBus_storage_non_convex_2_5) +-1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) +<= 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_non_convex_0)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_total(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_non_convex_1)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_total(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_total(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_old(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_non_convex_2)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_total(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_total(storage_non_convex_2) ++1 GenericInvestmentStorageBlock_old(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage_non_convex_0)_: ++1 GenericInvestmentStorageBlock_old_end(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage_non_convex_1)_: ++1 GenericInvestmentStorageBlock_old_end(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_end(storage_non_convex_2)_: ++1 GenericInvestmentStorageBlock_old_end(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage_non_convex_0)_: ++1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage_non_convex_1)_: ++1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule_exo(storage_non_convex_2)_: ++1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage_non_convex_0)_: +-1 GenericInvestmentStorageBlock_old_end(storage_non_convex_0) +-1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_old(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage_non_convex_1)_: ++1 GenericInvestmentStorageBlock_old(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_old_end(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_old_rule(storage_non_convex_2)_: ++1 GenericInvestmentStorageBlock_old(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_old_end(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_old_exo(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_initially_empty(storage_non_convex_0)_: ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_0_1)_: +-0.97 flow(electricityBus_storage_non_convex_0_1) ++1.1627906976744187 flow(storage_non_convex_electricityBus_0_1) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_1_2)_: +-0.97 flow(electricityBus_storage_non_convex_1_2) ++1.1627906976744187 flow(storage_non_convex_electricityBus_1_2) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_1_3)_: +-0.97 flow(electricityBus_storage_non_convex_1_3) ++1.1627906976744187 flow(storage_non_convex_electricityBus_1_3) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_2_4)_: +-0.97 flow(electricityBus_storage_non_convex_2_4) ++1.1627906976744187 flow(storage_non_convex_electricityBus_2_4) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) += 0 + +c_e_GenericInvestmentStorageBlock_balance(storage_non_convex_2_5)_: +-0.97 flow(electricityBus_storage_non_convex_2_5) ++1.1627906976744187 flow(storage_non_convex_electricityBus_2_5) +-0.87 GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_5) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage_non_convex_0)_: ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage_non_convex_1)_: ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_inflow(storage_non_convex_2)_: ++1 InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_2) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage_non_convex_0)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_0) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage_non_convex_1)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_1) += 0 + +c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage_non_convex_2)_: ++1 InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) +-0.16666666666666666 GenericInvestmentStorageBlock_total(storage_non_convex_2) += 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_0_0)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_0_1)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_0) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_1_2)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_1_3)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_1) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_2_4)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_2) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) +<= 0 + +c_u_GenericInvestmentStorageBlock_max_storage_content(storage_non_convex_2_5)_: +-0.9 GenericInvestmentStorageBlock_total(storage_non_convex_2) ++1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_5) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_0_0)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_0) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_0_1)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_0) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_1_2)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_1_3)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_1) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_2_4)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) +<= 0 + +c_u_GenericInvestmentStorageBlock_min_storage_content(storage_non_convex_2_5)_: ++0.1 GenericInvestmentStorageBlock_total(storage_non_convex_2) +-1 GenericInvestmentStorageBlock_storage_content(storage_non_convex_5) +<= 0 + +c_l_GenericInvestmentStorageBlock_limit_max(storage_non_convex_0)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_0) ++244 GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_max(storage_non_convex_1)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_1) ++244 GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_max(storage_non_convex_2)_: +-1 GenericInvestmentStorageBlock_invest(storage_non_convex_2) ++244 GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_min(storage_non_convex_0)_: ++1 GenericInvestmentStorageBlock_invest(storage_non_convex_0) +-12 GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_min(storage_non_convex_1)_: ++1 GenericInvestmentStorageBlock_invest(storage_non_convex_1) +-12 GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) +>= 0 + +c_l_GenericInvestmentStorageBlock_limit_min(storage_non_convex_2)_: ++1 GenericInvestmentStorageBlock_invest(storage_non_convex_2) +-12 GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) +>= 0 + +bounds + 0 <= flow(electricityBus_storage_non_convex_0_0) <= +inf + 0 <= flow(electricityBus_storage_non_convex_0_1) <= +inf + 0 <= flow(electricityBus_storage_non_convex_1_2) <= +inf + 0 <= flow(electricityBus_storage_non_convex_1_3) <= +inf + 0 <= flow(electricityBus_storage_non_convex_2_4) <= +inf + 0 <= flow(electricityBus_storage_non_convex_2_5) <= +inf + 0 <= flow(storage_non_convex_electricityBus_0_0) <= +inf + 0 <= flow(storage_non_convex_electricityBus_0_1) <= +inf + 0 <= flow(storage_non_convex_electricityBus_1_2) <= +inf + 0 <= flow(storage_non_convex_electricityBus_1_3) <= +inf + 0 <= flow(storage_non_convex_electricityBus_2_4) <= +inf + 0 <= flow(storage_non_convex_electricityBus_2_5) <= +inf + 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_0) <= 244 + 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_1) <= 244 + 0 <= GenericInvestmentStorageBlock_invest(storage_non_convex_2) <= 244 + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_total(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_total(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_invest(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_non_convex_electricityBus_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(electricityBus_storage_non_convex_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage_non_convex_electricityBus_0) <= +inf + 0 <= InvestmentFlowBlock_old(electricityBus_storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_total(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old_end(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_old_exo(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_old(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_0) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_1) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_2) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_3) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_4) <= +inf + 0 <= GenericInvestmentStorageBlock_storage_content(storage_non_convex_5) <= +inf + 0 <= GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) <= 1 + 0 <= GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) <= 1 + 0 <= GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) <= 1 +binary + GenericInvestmentStorageBlock_invest_status(storage_non_convex_0) + GenericInvestmentStorageBlock_invest_status(storage_non_convex_1) + GenericInvestmentStorageBlock_invest_status(storage_non_convex_2) +end diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index 4d4fa1700..79db5642b 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -1917,6 +1917,41 @@ def test_nonconvex_investment_storage_without_offset(self): self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_without_offset_multi_period.lp") + def test_nonconvex_investment_storage_without_offset_remaining_value(self): + """All invest variables are coupled. The invest variables of the Flows + will be created during the initialisation of the storage e.g. battery + """ + bel = solph.buses.Bus(label="electricityBus") + + storage = solph.components.GenericStorage( + label="storage_non_convex", + inputs={bel: solph.flows.Flow(variable_costs=56)}, + outputs={bel: solph.flows.Flow(variable_costs=24)}, + nominal_storage_capacity=None, + loss_rate=0.13, + max_storage_level=0.9, + min_storage_level=0.1, + invest_relation_input_capacity=1 / 6, + invest_relation_output_capacity=1 / 6, + inflow_conversion_factor=0.97, + outflow_conversion_factor=0.86, + lifetime_inflow=20, + lifetime_outflow=20, + investment=solph.Investment( + ep_costs=141, + maximum=244, + minimum=12, + nonconvex=True, + lifetime=20, + ), + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(bel, storage) + self.compare_lp_files( + "storage_invest_without_offset_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_nonconvex_investment_storage_with_offset(self): """All invest variables are coupled. The invest variables of the Flows will be created during the initialisation of the storage e.g. battery @@ -1949,6 +1984,42 @@ def test_nonconvex_investment_storage_with_offset(self): self.energysystem.add(bel, storage) self.compare_lp_files("storage_invest_with_offset_multi_period.lp") + def test_nonconvex_investment_storage_with_offset_remaining_value(self): + """All invest variables are coupled. The invest variables of the Flows + will be created during the initialisation of the storage e.g. battery + """ + bel = solph.buses.Bus(label="electricityBus") + + storage = solph.components.GenericStorage( + label="storage_non_convex", + inputs={bel: solph.flows.Flow(variable_costs=56)}, + outputs={bel: solph.flows.Flow(variable_costs=24)}, + nominal_storage_capacity=None, + loss_rate=0.13, + max_storage_level=0.9, + min_storage_level=0.1, + invest_relation_input_capacity=1 / 6, + invest_relation_output_capacity=1 / 6, + inflow_conversion_factor=0.97, + outflow_conversion_factor=0.86, + lifetime_inflow=20, + lifetime_outflow=20, + investment=solph.Investment( + ep_costs=145, + minimum=19, + offset=5, + nonconvex=True, + maximum=1454, + lifetime=20, + ), + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(bel, storage) + self.compare_lp_files( + "storage_invest_with_offset_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_nonconvex_invest_storage_all_nonconvex(self): """All invest variables are free and nonconvex.""" b1 = solph.buses.Bus(label="bus1") @@ -2015,6 +2086,34 @@ def test_nonconvex_invest_sink_without_offset(self): self.energysystem.add(bel, sink) self.compare_lp_files("flow_invest_without_offset_multi_period.lp") + def test_nonconvex_invest_sink_without_offset_remaining_value(self): + """Non convex invest flow without offset, with minimum.""" + bel = solph.buses.Bus(label="electricityBus") + + sink = solph.components.Sink( + label="sink_nonconvex_invest", + inputs={ + bel: solph.flows.Flow( + summed_max=2.3, + variable_costs=25, + max=0.8, + investment=solph.Investment( + ep_costs=500, + minimum=15, + nonconvex=True, + maximum=172, + lifetime=20, + ), + ) + }, + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(bel, sink) + self.compare_lp_files( + "flow_invest_without_offset_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_nonconvex_invest_source_with_offset(self): """Non convex invest flow with offset, with minimum.""" bel = solph.buses.Bus(label="electricityBus") @@ -2040,6 +2139,35 @@ def test_nonconvex_invest_source_with_offset(self): self.energysystem.add(bel, source) self.compare_lp_files("flow_invest_with_offset_multi_period.lp") + def test_nonconvex_invest_source_with_offset_remaining_value(self): + """Non convex invest flow with offset, with minimum.""" + bel = solph.buses.Bus(label="electricityBus") + + source = solph.components.Source( + label="source_nonconvex_invest", + outputs={ + bel: solph.flows.Flow( + summed_max=2.3, + variable_costs=25, + max=0.8, + investment=solph.Investment( + ep_costs=500, + minimum=15, + maximum=20, + offset=34, + nonconvex=True, + lifetime=20, + ), + ) + }, + ) + self.energysystem.use_remaining_value = True + self.energysystem.add(bel, source) + self.compare_lp_files( + "flow_invest_with_offset_multi_period_remaining_value.lp" + ) + self.energysystem.use_remaining_value = False + def test_nonconvex_invest_source_with_offset_no_minimum(self): """Non convex invest flow with offset, without minimum.""" bel = solph.buses.Bus(label="electricityBus") From 6cb4bbfc96e3bbd3a939aeb6a231e3ba227db458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Fri, 13 Oct 2023 17:21:31 +0200 Subject: [PATCH 080/180] Test Future warning in Flow invenstment --- tests/test_solph_network_classes.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_solph_network_classes.py b/tests/test_solph_network_classes.py index fa403541a..bce095289 100644 --- a/tests/test_solph_network_classes.py +++ b/tests/test_solph_network_classes.py @@ -87,6 +87,12 @@ def test_wrong_combination_invest_and_nominal_value(): solph.flows.Flow(investment=solph.Investment(), nominal_value=4) +def test_invest_attribute_warning(): + msg = "For backward compatibility, the option investment overwrites" + with pytest.warns(FutureWarning, match=msg): + solph.flows.Flow(investment=solph.Investment()) + + def test_fixed_costs_warning(): msg = ( "Be aware that the fixed costs attribute is only\n" From 321a35af47bd7454356a1cb2dae8963ca161b3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 16 Oct 2023 19:34:57 +0200 Subject: [PATCH 081/180] Revert "Delete warning about timeincrement in EnergySystem" This reverts commit 2129b0a800a7109f052023a7f60e0e516ef05348. --- src/oemof/solph/_energy_system.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index f566c51c7..89c3d22d3 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -130,6 +130,13 @@ def __init__( "conflicting to each other." ) raise AttributeError(msg) + else: + msg = ( + "Ensure that your timeindex and timeincrement are " + "consistent.\nIf you are not considering non-equidistant " + "timeindices, consider only specifying a timeindex." + ) + warnings.warn(msg, debugging.ExperimentalFeatureWarning) elif timeindex is not None and timeincrement is None: df = pd.DataFrame(timeindex) From 561688d27465d467c5f28bad43b9bf964148434d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 16 Oct 2023 19:40:47 +0200 Subject: [PATCH 082/180] Tell about need for timeincrement in MP models As described in #979, timeincrement currently needs to be set for multi period optimisation models. --- src/oemof/solph/_energy_system.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 89c3d22d3..de2d2ad79 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -133,8 +133,7 @@ def __init__( else: msg = ( "Ensure that your timeindex and timeincrement are " - "consistent.\nIf you are not considering non-equidistant " - "timeindices, consider only specifying a timeindex." + "consistent." ) warnings.warn(msg, debugging.ExperimentalFeatureWarning) From 555234bb170b3e0df91f5645dde4ae12ec52d5fa Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 20 Oct 2023 10:22:41 +0200 Subject: [PATCH 083/180] Rephrase & replace formula occurences of "whereby" --- src/oemof/solph/components/_generic_storage.py | 10 +++++----- src/oemof/solph/components/experimental/_sink_dsm.py | 6 +++--- src/oemof/solph/flows/_investment_flow_block.py | 9 +++++---- src/oemof/solph/flows/_simple_flow_block.py | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index fdb7a1e24..cd1b2c3fe 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -442,7 +442,7 @@ class GenericStorageBlock(ScalarBlock): \displaystyle \sum_{pp=0}^{year_{max}} E_{nom} \cdot c_{fixed}(pp) \cdot DF^{-pp} - whereby: + where: * :math:`DF=(1+dr)` is the discount factor with discount rate :math:`dr`. * :math:`year_{max}` denotes the last year of the optimization @@ -756,7 +756,7 @@ class GenericInvestmentStorageBlock(ScalarBlock): & \forall p \in \textrm{PERIODS} - whereby: + where: * (*) is only performed for the first period the condition is True. A decommissioning flag is then set to True to prevent having falsely @@ -888,7 +888,7 @@ class GenericInvestmentStorageBlock(ScalarBlock): E_{invest}(0) \cdot c_{invest,var}(0) + c_{invest,fix}(0) \cdot b_{invest}(0)\\ - Whereby 0 denotes the 0th (investment) period since + Where 0 denotes the 0th (investment) period since in a standard model, there is only this one period. *Multi-period model* @@ -962,7 +962,7 @@ class GenericInvestmentStorageBlock(ScalarBlock): \sum_{pp=0}^{limit_{exo}} E_{exist} \cdot c_{fixed}(pp) \cdot DF^{-pp} - whereby: + where: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` @@ -1040,7 +1040,7 @@ class GenericInvestmentStorageBlock(ScalarBlock): | Old (nominal) capacity of the storage | to be decommissioned in period p | which was endogenously determined by :math:`E_{invest}(p_{comm})` - | whereby :math:`p_{comm}` is the commissioning period" + | where :math:`p_{comm}` is the commissioning period" ":math:`E(-1)`", ":attr:`init_cap[n]`", "Initial storage capacity (before timestep 0)" ":math:`b_{invest}(p)`", ":attr:`invest_status[i, o, p]`", "Binary diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index 88c0335c7..9d9a0c758 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -832,7 +832,7 @@ class SinkDSMOemofInvestmentBlock(ScalarBlock): & \quad \quad \quad \quad \forall p, t \in \textrm{TIMEINDEX} \\ - whereby: + where: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` @@ -2352,7 +2352,7 @@ class SinkDSMDIWInvestmentBlock(ScalarBlock): & \quad \quad \quad \quad \forall p, t \in \textrm{TIMEINDEX} \\ - whereby: + where: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` @@ -4620,7 +4620,7 @@ class SinkDSMDLRInvestmentBlock(ScalarBlock): \cdot \omega_{t} \cdot DF^{-p} \\ & \quad \quad \quad \quad \forall p, t \in \textrm{TIMEINDEX} \\ - whereby: + where: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 514a7343f..738ffd77f 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -336,7 +336,7 @@ def _create_constraints(self): & \forall p \in \textrm{PERIODS} - whereby: + where: * (*) is only performed for the first period the condition is True. A decommissioning flag is then set to True @@ -770,7 +770,7 @@ def _objective_expression(self): P_{invest}(0) \cdot c_{invest,var}(0) + c_{invest,fix}(0) \cdot Y_{invest}(0) \\ - Whereby 0 denotes the 0th (investment) period since + Where 0 denotes the 0th (investment) period since in a standard model, there is only this one period. *Multi-period model* @@ -848,7 +848,7 @@ def _objective_expression(self): \cdot DF^{-pp} - whereby: + where: * :math:`A(c_{invest,var}(p), l, ir)` A is the annuity for investment expenses :math:`c_{invest,var}(p)`, lifetime :math:`l` @@ -883,7 +883,8 @@ def _objective_expression(self): & ANF(d, ir)=\frac {(1+ir)^d \cdot ir} {(1+ir)^d - 1} - They are retrieved, using oemof.tools.economics annuity function. + They are derived using the reciprocal of the oemof.tools.economics + annuity function with a capex of 1. The interest rate :math:`ir` for the annuity is defined as weighted average costs of capital (wacc) and assumed constant over time. """ diff --git a/src/oemof/solph/flows/_simple_flow_block.py b/src/oemof/solph/flows/_simple_flow_block.py index 32ba487d4..eb4d55c26 100644 --- a/src/oemof/solph/flows/_simple_flow_block.py +++ b/src/oemof/solph/flows/_simple_flow_block.py @@ -415,7 +415,7 @@ def _objective_expression(self): .. math:: \sum_{(i,o)} \sum_t P(t) \cdot w(t) \cdot c_{var}(i, o, t) - whereby :math:`w(t)` is the objective weighting. + where :math:`w(t)` is the objective weighting. In a multi-period model, in contrast, the following parts of the objective function are created: From c75ecec711bf9031ec1d8e87cf8358c36b44a2ff Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 20 Oct 2023 10:31:32 +0200 Subject: [PATCH 084/180] Remove code duplication --- .../solph/components/_generic_storage.py | 22 ++++++++-------- .../solph/flows/_investment_flow_block.py | 25 ++++++++----------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index cd1b2c3fe..244e75348 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1953,20 +1953,20 @@ def _evaluate_remaining_value_difference( present_value_factor_remaining = 1 / economics.annuity( capex=1, n=remaining_lifetime, wacc=interest ) + convex_investment_costs = ( + self.invest[n, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) if nonconvex: - return ( - self.invest[n, p] - * (remaining_annuity - original_annuity) - * present_value_factor_remaining - + self.invest_status[n, p] - * (n.investment.offset[-1] - n.investment.offset[p]) + return convex_investment_costs + self.invest_status[ + n, p + ] * ( + n.investment.offset[-1] - + n.investment.offset[p] ) * (1 + m.discount_rate) ** (-end_year_of_optimization) else: - return ( - self.invest[n, p] - * (remaining_annuity - original_annuity) - * present_value_factor_remaining - ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + return convex_investment_costs else: return 0 else: diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 738ffd77f..e98fd7c60 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -1110,23 +1110,20 @@ def _evaluate_remaining_value_difference( present_value_factor_remaining = 1 / economics.annuity( capex=1, n=remaining_lifetime, wacc=interest ) + convex_investment_costs = ( + self.invest[i, o, p] + * (remaining_annuity - original_annuity) + * present_value_factor_remaining + ) * (1 + m.discount_rate) ** (-end_year_of_optimization) if nonconvex: - return ( - self.invest[i, o, p] - * (remaining_annuity - original_annuity) - * present_value_factor_remaining - + self.invest_status[i, o, p] - * ( - m.flows[i, o].investment.offset[-1] - - m.flows[i, o].investment.offset[p] - ) + return convex_investment_costs + self.invest_status[ + i, o, p + ] * ( + m.flows[i, o].investment.offset[-1] + - m.flows[i, o].investment.offset[p] ) * (1 + m.discount_rate) ** (-end_year_of_optimization) else: - return ( - self.invest[i, o, p] - * (remaining_annuity - original_annuity) - * present_value_factor_remaining - ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + return convex_investment_costs else: return 0 else: From f542a7caf8e73efd03b9297ffda9e9bd326fa04b Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 20 Oct 2023 10:32:33 +0200 Subject: [PATCH 085/180] Fix formatting --- src/oemof/solph/components/_generic_storage.py | 9 +++++---- src/oemof/solph/flows/_investment_flow_block.py | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 244e75348..4145d8428 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1961,10 +1961,11 @@ def _evaluate_remaining_value_difference( if nonconvex: return convex_investment_costs + self.invest_status[ n, p - ] * ( - n.investment.offset[-1] - - n.investment.offset[p] - ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + ] * (n.investment.offset[-1] - n.investment.offset[p]) * ( + 1 + m.discount_rate + ) ** ( + -end_year_of_optimization + ) else: return convex_investment_costs else: diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index e98fd7c60..a8d795ce7 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -1121,7 +1121,11 @@ def _evaluate_remaining_value_difference( ] * ( m.flows[i, o].investment.offset[-1] - m.flows[i, o].investment.offset[p] - ) * (1 + m.discount_rate) ** (-end_year_of_optimization) + ) * ( + 1 + m.discount_rate + ) ** ( + -end_year_of_optimization + ) else: return convex_investment_costs else: From f73e7db6f50ce1e8fc9971c4b6636679099a2b3b Mon Sep 17 00:00:00 2001 From: lensum <80690396+lensum@users.noreply.github.com> Date: Fri, 20 Oct 2023 16:54:55 +0200 Subject: [PATCH 086/180] make BasicModel consider all constraint groups --- src/oemof/solph/_models.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/oemof/solph/_models.py b/src/oemof/solph/_models.py index 65c23c8eb..b9ba79e8b 100644 --- a/src/oemof/solph/_models.py +++ b/src/oemof/solph/_models.py @@ -132,12 +132,21 @@ def __init__(self, energysystem, **kwargs): "constraint_groups", [] ) - self._constraint_groups += [ - i - for i in self.es.groups - if hasattr(i, "CONSTRAINT_GROUP") - and i not in self._constraint_groups - ] + if self.is_cellular: + for es in energysystem: + self._constraint_groups += [ + i + for i in es.groups + if hasattr(i, "CONSTRAINT_GROUP") + and i not in self._constraint_groups + ] + else: + self._constraint_groups += [ + i + for i in self.es.groups + if hasattr(i, "CONSTRAINT_GROUP") + and i not in self._constraint_groups + ] self.flows = self.es.flows() if self.is_cellular: From db875422cbede027788ef92fd1e55177f4dd1ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 23 Oct 2023 09:19:21 +0200 Subject: [PATCH 087/180] Specify time unit to be hours The time unit currently is hardcoded to be hours. The documentation now reflects that. --- .../solph/components/_generic_storage.py | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index fe99af99d..352fd64db 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -80,7 +80,7 @@ class GenericStorage(Node): Couple storage level of first and last time step. (Total inflow and total outflow are balanced.) loss_rate : numeric (iterable or scalar) - The relative loss of the storage content per time unit (e.g. hour). + The relative loss of the storage content per hour. fixed_losses_relative : numeric (iterable or scalar), :math:`\gamma(t)` Losses per hour that are independent of the storage content but proportional to nominal storage capacity. @@ -395,16 +395,12 @@ class GenericStorageBlock(ScalarBlock): :math:`c_{max}(t)` maximum allowed storage `max_storage_level[t]` :math:`\beta(t)` fraction of lost energy `loss_rate[t]` as share of - :math:`E(t)` - per time unit - (e.g. hour) + :math:`E(t)` per hour :math:`\gamma(t)` fixed loss of energy `fixed_losses_relative[t]` - relative to - :math:`E_{nom}` per - time unit (e.g. hour) + per hour relative to + :math:`E_{nom}` :math:`\delta(t)` absolute fixed loss `fixed_losses_absolute[t]` - of energy per - time unit (e.g. hour) + of energy per hour :math:`\dot{E}_i(t)` energy flowing in `inputs` :math:`\dot{E}_o(t)` energy flowing out `outputs` :math:`\eta_i(t)` conversion factor `inflow_conversion_factor[t]` @@ -1079,11 +1075,11 @@ class GenericInvestmentStorageBlock(ScalarBlock): ":math:`r_{in,out}`", ":attr:`invest_relation_input_output`", " Relation of nominal in- and outflow" ":math:`\beta(t)`", "`loss_rate[t]`", "Fraction of lost energy - as share of :math:`E(t)` per time unit" + as share of :math:`E(t)` per hour" ":math:`\gamma(t)`", "`fixed_losses_relative[t]`", "Fixed loss - of energy relative to :math:`E_{invest} + E_{exist}` per time unit" + of energy relative to :math:`E_{invest} + E_{exist}` per hour" ":math:`\delta(t)`", "`fixed_losses_absolute[t]`", "Absolute - fixed loss of energy per time unit" + fixed loss of energy per hour" ":math:`\eta_i(t)`", "`inflow_conversion_factor[t]`", " Conversion factor (i.e. efficiency) when storing energy" ":math:`\eta_o(t)`", "`outflow_conversion_factor[t]`", " From 54fac89ca62809f6693560f433d9edd5b1ce979f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 23 Oct 2023 09:24:42 +0200 Subject: [PATCH 088/180] Speak of time steps in minimum "time" constraints The constraints are actually defined in time steps. (The documentation asked for integers before, so it could be seen from the context.) --- src/oemof/solph/_options.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index 42bf15885..b57c153d6 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -185,13 +185,13 @@ class NonConvex: inactivity_costs : numeric (iterable or scalar) Costs associated with not operating the flow. minimum_uptime : numeric (1 or positive integer) - Minimum time that a flow must be greater then its minimum flow after - startup. Be aware that minimum up and downtimes can contradict each - other and may lead to infeasible problems. + Minimum number of time steps that a flow must be greater then its + minimum flow after startup. Be aware that minimum up and downtimes + can contradict each other and may lead to infeasible problems. minimum_downtime : numeric (1 or positive integer) - Minimum time a flow is forced to zero after shutting down. - Be aware that minimum up and downtimes can contradict each - other and may to infeasible problems. + Minimum number of time steps a flow is forced to zero after + shutting down. Be aware that minimum up and downtimes can + contradict each other and may to infeasible problems. maximum_startups : numeric (0 or positive integer) Maximum number of start-ups in the optimization timeframe. maximum_shutdowns : numeric (0 or positive integer) From 87377e713ab460451e6c00b34668dfac9c819637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 23 Oct 2023 09:45:51 +0200 Subject: [PATCH 089/180] Specify RTD build OS It is now mandatory to do so to geht the docs built. --- .readthedocs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index aff41b4cf..44b41b104 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,6 +1,7 @@ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details version: 2 build: + os: ubuntu-22.04 apt_packages: - coinor-cbc sphinx: From 498d9a6560441bc4975e57f6f5bec3cacb51f53c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 23 Oct 2023 09:50:40 +0200 Subject: [PATCH 090/180] Specify tools in .readthedocs.yaml This is now mandatory to have RTD builds. --- .readthedocs.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 44b41b104..6a3383206 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -2,6 +2,8 @@ version: 2 build: os: ubuntu-22.04 + tools: + python: "3.8" apt_packages: - coinor-cbc sphinx: From 16054cae9d99b2e70d7548fc8a96f5e8ca7bb878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 23 Oct 2023 09:54:18 +0200 Subject: [PATCH 091/180] Update python version .readthedocs.yaml The format seems to be different from the one below. --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 6a3383206..9ed0e7a57 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -3,7 +3,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.8" + python: 3.8 apt_packages: - coinor-cbc sphinx: From 39f59f5e83cc7ad432e9c9c2bb4f55ed0b86e135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 23 Oct 2023 09:56:30 +0200 Subject: [PATCH 092/180] Fix python version in .readthedocs.yaml --- .readthedocs.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 9ed0e7a57..a5016d1e6 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -3,14 +3,13 @@ version: 2 build: os: ubuntu-22.04 tools: - python: 3.8 + python: "3.8" apt_packages: - coinor-cbc sphinx: configuration: docs/conf.py formats: [] python: - version: "3.8" install: - requirements: docs/requirements.txt - method: pip From fb1c5f79e57cc283ed8a610b7f8f47ffc22c9fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 25 Oct 2023 13:30:50 +0200 Subject: [PATCH 093/180] Bump version number --- .bumpversion.cfg | 2 +- VERSION | 2 +- docs/conf.py | 2 +- setup.py | 2 +- src/oemof/solph/__init__.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index d2a410849..955f328cd 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.5.2dev1 +current_version = 0.5.2dev2 commit = True tag = True diff --git a/VERSION b/VERSION index 26d478d27..ae000fe0a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -__version__ = "0.5.2dev1" +__version__ = "0.5.2dev2" diff --git a/docs/conf.py b/docs/conf.py index e94a07367..6a7d75dea 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,7 @@ def setup(app): year = "2014-2023" author = "oemof-developer-group" copyright = "{0}, {1}".format(year, author) -version = release = "0.5.2dev1" +version = release = "0.5.2dev2" pygments_style = "trac" templates_path = ["."] diff --git a/setup.py b/setup.py index 77028a838..818f2ea0c 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ def read(*names, **kwargs): setup( name="oemof.solph", - version="0.5.2dev1", + version="0.5.2dev2", license="MIT", description=( "A model generator for energy system modelling and optimisation." diff --git a/src/oemof/solph/__init__.py b/src/oemof/solph/__init__.py index af4cd7eff..d8632f71c 100644 --- a/src/oemof/solph/__init__.py +++ b/src/oemof/solph/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.5.2dev1" +__version__ = "0.5.2dev2" from . import buses from . import components From 973117df72fb7def276d75d039f3646db2e01389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 9 Nov 2023 13:28:20 +0100 Subject: [PATCH 094/180] Adjust to energy_system.nodes being a dictionary --- src/oemof/solph/_models.py | 3 +-- src/oemof/solph/flows/experimental/_electrical_line.py | 2 +- src/oemof/solph/processing.py | 4 ++-- tests/test_models.py | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/oemof/solph/_models.py b/src/oemof/solph/_models.py index b9ba79e8b..271f5e54f 100644 --- a/src/oemof/solph/_models.py +++ b/src/oemof/solph/_models.py @@ -406,8 +406,7 @@ def _add_parent_block_sets(self): if self.is_cellular: # collect all nodes from the child cells for cell in self.ec: - for node in cell.nodes: - self.nodes.append(node) + self.nodes.update(cell.nodes) # create set with all nodes self.NODES = po.Set(initialize=[n for n in self.nodes]) diff --git a/src/oemof/solph/flows/experimental/_electrical_line.py b/src/oemof/solph/flows/experimental/_electrical_line.py index e96f85de7..292dd81b5 100644 --- a/src/oemof/solph/flows/experimental/_electrical_line.py +++ b/src/oemof/solph/flows/experimental/_electrical_line.py @@ -148,7 +148,7 @@ def _create(self, group=None): # create voltage angle variables self.ELECTRICAL_BUSES = Set( - initialize=[n for n in m.es.nodes if isinstance(n, ElectricalBus)] + initialize=[n for n in m.es.nodes.values() if isinstance(n, ElectricalBus)] ) def _voltage_angle_bounds(block, b, t): diff --git a/src/oemof/solph/processing.py b/src/oemof/solph/processing.py index c641fd436..543691ad0 100644 --- a/src/oemof/solph/processing.py +++ b/src/oemof/solph/processing.py @@ -611,9 +611,9 @@ def remove_nones(com): # Check if system is es or om: if system.__class__.__name__ == "EnergySystem": - components = system.flows() if get_flows else system.nodes + components = system.flows() if get_flows else system.nodes.values() else: - components = system.flows if get_flows else system.es.nodes + components = system.flows if get_flows else system.es.nodes.values() data = {} for com_key in components: diff --git a/tests/test_models.py b/tests/test_models.py index 3ac3938eb..df8cbfe20 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -137,7 +137,7 @@ def test_sub_cell_node_consideration(): es.add(bus_es) ec_1.add(bus_ec_1) m = solph.Model(energysystem=[es, ec_1]) - assert bus_ec_1 in m.nodes + assert bus_ec_1 in m.nodes.values() def test_sub_cell_flow_consideration(): From 9fbe62a183b6879a9c72f0cd0dbc234e4ee210da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 9 Nov 2023 13:58:12 +0100 Subject: [PATCH 095/180] Adjust to energy_system.node and .nodes .node now should be a dictionary, but .nodes should be dict_values. --- src/oemof/solph/_models.py | 6 +++--- src/oemof/solph/flows/experimental/_electrical_line.py | 2 +- src/oemof/solph/processing.py | 4 ++-- tests/test_models.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/oemof/solph/_models.py b/src/oemof/solph/_models.py index 271f5e54f..ea0c58b3b 100644 --- a/src/oemof/solph/_models.py +++ b/src/oemof/solph/_models.py @@ -402,13 +402,13 @@ def _add_parent_block_sets(self): """Add all basic sets to the model, i.e. NODES, TIMESTEPS and FLOWS. Also create sets PERIODS and TIMEINDEX used for multi-period models. """ - self.nodes = self.es.nodes + self.node = self.es.node if self.is_cellular: # collect all nodes from the child cells for cell in self.ec: - self.nodes.update(cell.nodes) + self.node.update(cell.node) # create set with all nodes - self.NODES = po.Set(initialize=[n for n in self.nodes]) + self.NODES = po.Set(initialize=[n for n in self.node]) if self.es.timeincrement is None: msg = ( diff --git a/src/oemof/solph/flows/experimental/_electrical_line.py b/src/oemof/solph/flows/experimental/_electrical_line.py index 292dd81b5..e96f85de7 100644 --- a/src/oemof/solph/flows/experimental/_electrical_line.py +++ b/src/oemof/solph/flows/experimental/_electrical_line.py @@ -148,7 +148,7 @@ def _create(self, group=None): # create voltage angle variables self.ELECTRICAL_BUSES = Set( - initialize=[n for n in m.es.nodes.values() if isinstance(n, ElectricalBus)] + initialize=[n for n in m.es.nodes if isinstance(n, ElectricalBus)] ) def _voltage_angle_bounds(block, b, t): diff --git a/src/oemof/solph/processing.py b/src/oemof/solph/processing.py index 543691ad0..c641fd436 100644 --- a/src/oemof/solph/processing.py +++ b/src/oemof/solph/processing.py @@ -611,9 +611,9 @@ def remove_nones(com): # Check if system is es or om: if system.__class__.__name__ == "EnergySystem": - components = system.flows() if get_flows else system.nodes.values() + components = system.flows() if get_flows else system.nodes else: - components = system.flows if get_flows else system.es.nodes.values() + components = system.flows if get_flows else system.es.nodes data = {} for com_key in components: diff --git a/tests/test_models.py b/tests/test_models.py index df8cbfe20..e2a2b1dfa 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -137,7 +137,7 @@ def test_sub_cell_node_consideration(): es.add(bus_es) ec_1.add(bus_ec_1) m = solph.Model(energysystem=[es, ec_1]) - assert bus_ec_1 in m.nodes.values() + assert bus_ec_1 in m.node.values() def test_sub_cell_flow_consideration(): From 414ca332872f521746ce12eda226fbdbab2e55e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 9 Nov 2023 13:58:58 +0100 Subject: [PATCH 096/180] Adhere to Black --- src/oemof/solph/_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oemof/solph/_models.py b/src/oemof/solph/_models.py index ea0c58b3b..e06064a7b 100644 --- a/src/oemof/solph/_models.py +++ b/src/oemof/solph/_models.py @@ -406,7 +406,7 @@ def _add_parent_block_sets(self): if self.is_cellular: # collect all nodes from the child cells for cell in self.ec: - self.node.update(cell.node) + self.node.update(cell.node) # create set with all nodes self.NODES = po.Set(initialize=[n for n in self.node]) From 36e5f42a0157ffb8d88cdb6146c511a3b58dad21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 9 Nov 2023 14:12:31 +0100 Subject: [PATCH 097/180] Let Model.nodes be a list This aligns with the plan to let network.EnergySystem.nodes return the dict_values, so it's like a list (at least no keys). --- src/oemof/solph/_models.py | 6 +++--- tests/test_models.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/oemof/solph/_models.py b/src/oemof/solph/_models.py index e06064a7b..59ab74188 100644 --- a/src/oemof/solph/_models.py +++ b/src/oemof/solph/_models.py @@ -402,13 +402,13 @@ def _add_parent_block_sets(self): """Add all basic sets to the model, i.e. NODES, TIMESTEPS and FLOWS. Also create sets PERIODS and TIMEINDEX used for multi-period models. """ - self.node = self.es.node + self.nodes = list(self.es.nodes) if self.is_cellular: # collect all nodes from the child cells for cell in self.ec: - self.node.update(cell.node) + self.nodes.extend(cell.nodes) # create set with all nodes - self.NODES = po.Set(initialize=[n for n in self.node]) + self.NODES = po.Set(initialize=[n for n in self.nodes]) if self.es.timeincrement is None: msg = ( diff --git a/tests/test_models.py b/tests/test_models.py index e2a2b1dfa..3ac3938eb 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -137,7 +137,7 @@ def test_sub_cell_node_consideration(): es.add(bus_es) ec_1.add(bus_ec_1) m = solph.Model(energysystem=[es, ec_1]) - assert bus_ec_1 in m.node.values() + assert bus_ec_1 in m.nodes def test_sub_cell_flow_consideration(): From b2ab2a1bfc4117d90e98bfa3b133404c053f86e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 15 Nov 2023 15:38:09 +0100 Subject: [PATCH 098/180] Fix y intercept of OffsetConverter --- src/oemof/solph/components/_offset_converter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/oemof/solph/components/_offset_converter.py b/src/oemof/solph/components/_offset_converter.py index 606b0f3ad..847451c21 100644 --- a/src/oemof/solph/components/_offset_converter.py +++ b/src/oemof/solph/components/_offset_converter.py @@ -245,7 +245,7 @@ def _relation_rule(block): # `NonConvexFlow`. try: expr += ( - m.InvestNonConvexFlowBlock.status_nominal[ + m.InvestNonConvexFlowBlock.status[ n, o, t ] * n.coefficients[0][t] @@ -262,7 +262,7 @@ def _relation_rule(block): # (inside the `try` block) does not exist. except (KeyError, AttributeError): expr += ( - m.NonConvexFlowBlock.status_nominal[ + m.NonConvexFlowBlock.status[ n, o, t ] * n.coefficients[0][t] From 0657ea28711f22188e67d4be305492ac6192c04a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 15 Nov 2023 15:43:57 +0100 Subject: [PATCH 099/180] Adhere to Black --- src/oemof/solph/components/_offset_converter.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/oemof/solph/components/_offset_converter.py b/src/oemof/solph/components/_offset_converter.py index 847451c21..8369d8ded 100644 --- a/src/oemof/solph/components/_offset_converter.py +++ b/src/oemof/solph/components/_offset_converter.py @@ -245,9 +245,7 @@ def _relation_rule(block): # `NonConvexFlow`. try: expr += ( - m.InvestNonConvexFlowBlock.status[ - n, o, t - ] + m.InvestNonConvexFlowBlock.status[n, o, t] * n.coefficients[0][t] ) # `KeyError` occurs when more than one @@ -262,9 +260,7 @@ def _relation_rule(block): # (inside the `try` block) does not exist. except (KeyError, AttributeError): expr += ( - m.NonConvexFlowBlock.status[ - n, o, t - ] + m.NonConvexFlowBlock.status[n, o, t] * n.coefficients[0][t] ) block.relation.add((n, i, o, p, t), (expr == 0)) From 195db658d6a992696867e740187472a577516688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 15 Nov 2023 15:51:44 +0100 Subject: [PATCH 100/180] Adjust LP files in OffsetConverter test --- tests/lp_files/offsetconverter_nonconvex.lp | 6 +++--- tests/lp_files/offsetconverter_nonconvex_investment.lp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/lp_files/offsetconverter_nonconvex.lp b/tests/lp_files/offsetconverter_nonconvex.lp index 98ff1f1c0..62a306701 100644 --- a/tests/lp_files/offsetconverter_nonconvex.lp +++ b/tests/lp_files/offsetconverter_nonconvex.lp @@ -72,19 +72,19 @@ c_u_NonConvexFlowBlock_max(diesel_genset_bus_electricity_0_1)_: c_u_NonConvexFlowBlock_max(diesel_genset_bus_electricity_0_2)_: 1 flow(diesel_genset_bus_electricity_0_2) --1 NonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_2) +-1 NonConvexFlowBlock_status(diesel_genset_bus_electricity_2) <= 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_0)_: +0.5 flow(bus_diesel_diesel_genset_0_0) -1 flow(diesel_genset_bus_electricity_0_0) -+2.5 NonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_0) ++2.5 NonConvexFlowBlock_status(diesel_genset_bus_electricity_0) = 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_1)_: +0.5 flow(bus_diesel_diesel_genset_0_1) -1 flow(diesel_genset_bus_electricity_0_1) -+2.5 NonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_1) ++2.5 NonConvexFlowBlock_status(diesel_genset_bus_electricity_1) = 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_2)_: diff --git a/tests/lp_files/offsetconverter_nonconvex_investment.lp b/tests/lp_files/offsetconverter_nonconvex_investment.lp index 4b9755dd5..aa845ed66 100644 --- a/tests/lp_files/offsetconverter_nonconvex_investment.lp +++ b/tests/lp_files/offsetconverter_nonconvex_investment.lp @@ -119,19 +119,19 @@ c_u_InvestNonConvexFlowBlock_invest_nc_three(diesel_genset_bus_electricity_0_2)_ c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_0)_: +0.5 flow(bus_diesel_diesel_genset_0_0) -1 flow(diesel_genset_bus_electricity_0_0) -+2.5 InvestNonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_0) ++2.5 InvestNonConvexFlowBlock_status(diesel_genset_bus_electricity_0) = 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_1)_: +0.5 flow(bus_diesel_diesel_genset_0_1) -1 flow(diesel_genset_bus_electricity_0_1) -+2.5 InvestNonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_1) ++2.5 InvestNonConvexFlowBlock_status(diesel_genset_bus_electricity_1) = 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_2)_: +0.5 flow(bus_diesel_diesel_genset_0_2) -1 flow(diesel_genset_bus_electricity_0_2) -+2.5 InvestNonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_2) ++2.5 InvestNonConvexFlowBlock_status(diesel_genset_bus_electricity_2) = 0 bounds From 786585c53832f37c83f9ce5d22f5afb2533c770f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 15 Nov 2023 16:01:57 +0100 Subject: [PATCH 101/180] Adjust LP files in OffsetConverter test --- tests/lp_files/offsetconverter.lp | 12 ++++++------ tests/lp_files/offsetconverter_multi_period.lp | 12 ++++++------ tests/lp_files/offsetconverter_nonconvex.lp | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/lp_files/offsetconverter.lp b/tests/lp_files/offsetconverter.lp index 59b7c425e..a241b80fd 100644 --- a/tests/lp_files/offsetconverter.lp +++ b/tests/lp_files/offsetconverter.lp @@ -47,32 +47,32 @@ c_e_NonConvexFlowBlock_status_nominal_constraint(gasBus_gasboiler_2)_: c_u_NonConvexFlowBlock_min(gasBus_gasboiler_0_0)_: -1 flow(gasBus_gasboiler_0_0) -+0.32 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_0) ++0.32 NonConvexFlowBlock_status(gasBus_gasboiler_0) <= 0 c_u_NonConvexFlowBlock_min(gasBus_gasboiler_0_1)_: -1 flow(gasBus_gasboiler_0_1) -+0.32 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_1) ++0.32 NonConvexFlowBlock_status(gasBus_gasboiler_1) <= 0 c_u_NonConvexFlowBlock_min(gasBus_gasboiler_0_2)_: -1 flow(gasBus_gasboiler_0_2) -+0.32 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_2) ++0.32 NonConvexFlowBlock_status(gasBus_gasboiler_2) <= 0 c_u_NonConvexFlowBlock_max(gasBus_gasboiler_0_0)_: +1 flow(gasBus_gasboiler_0_0) --1 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_0) +-1 NonConvexFlowBlock_status(gasBus_gasboiler_0) <= 0 c_u_NonConvexFlowBlock_max(gasBus_gasboiler_0_1)_: +1 flow(gasBus_gasboiler_0_1) --1 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_1) +-1 NonConvexFlowBlock_status(gasBus_gasboiler_1) <= 0 c_u_NonConvexFlowBlock_max(gasBus_gasboiler_0_2)_: +1 flow(gasBus_gasboiler_0_2) --1 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_2) +-1 NonConvexFlowBlock_status(gasBus_gasboiler_2) <= 0 c_e_OffsetConverterBlock_relation(gasboiler_0_0)_: diff --git a/tests/lp_files/offsetconverter_multi_period.lp b/tests/lp_files/offsetconverter_multi_period.lp index 2f29944f2..fd0789adc 100644 --- a/tests/lp_files/offsetconverter_multi_period.lp +++ b/tests/lp_files/offsetconverter_multi_period.lp @@ -147,37 +147,37 @@ c_u_NonConvexFlowBlock_max(gasboiler_thermalBus_2_5)_: c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_0_0)_: +0.9 flow(gasBus_gasboiler_0_0) -1 flow(gasboiler_thermalBus_0_0) --17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_0) +-17 NonConvexFlowBlock_status(gasboiler_thermalBus_0) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_0_1)_: +0.9 flow(gasBus_gasboiler_0_1) -1 flow(gasboiler_thermalBus_0_1) --17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_1) +-17 NonConvexFlowBlock_status(gasboiler_thermalBus_1) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_1_2)_: +0.9 flow(gasBus_gasboiler_1_2) -1 flow(gasboiler_thermalBus_1_2) --17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_2) +-17 NonConvexFlowBlock_status(gasboiler_thermalBus_2) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_1_3)_: +0.9 flow(gasBus_gasboiler_1_3) -1 flow(gasboiler_thermalBus_1_3) --17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_3) +-17 NonConvexFlowBlock_status(gasboiler_thermalBus_3) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_2_4)_: +0.9 flow(gasBus_gasboiler_2_4) -1 flow(gasboiler_thermalBus_2_4) --17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_4) +-17 NonConvexFlowBlock_status(gasboiler_thermalBus_4) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_2_5)_: +0.9 flow(gasBus_gasboiler_2_5) -1 flow(gasboiler_thermalBus_2_5) --17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_5) +-17 NonConvexFlowBlock_status(gasboiler_thermalBus_5) = 0 bounds diff --git a/tests/lp_files/offsetconverter_nonconvex.lp b/tests/lp_files/offsetconverter_nonconvex.lp index 62a306701..c268d6616 100644 --- a/tests/lp_files/offsetconverter_nonconvex.lp +++ b/tests/lp_files/offsetconverter_nonconvex.lp @@ -90,7 +90,7 @@ c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_1)_ c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_2)_: +0.5 flow(bus_diesel_diesel_genset_0_2) -1 flow(diesel_genset_bus_electricity_0_2) -+2.5 NonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_2) ++2.5 NonConvexFlowBlock_status(diesel_genset_bus_electricity_2) = 0 bounds From 278182969c89965aae2e4d843726b695d18e4e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=B6nfeldt?= Date: Wed, 15 Nov 2023 16:16:58 +0100 Subject: [PATCH 102/180] Adjust LP files in OffsetConverter test --- tests/lp_files/offsetconverter_nonconvex.lp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lp_files/offsetconverter_nonconvex.lp b/tests/lp_files/offsetconverter_nonconvex.lp index c268d6616..d05b85060 100644 --- a/tests/lp_files/offsetconverter_nonconvex.lp +++ b/tests/lp_files/offsetconverter_nonconvex.lp @@ -72,7 +72,7 @@ c_u_NonConvexFlowBlock_max(diesel_genset_bus_electricity_0_1)_: c_u_NonConvexFlowBlock_max(diesel_genset_bus_electricity_0_2)_: 1 flow(diesel_genset_bus_electricity_0_2) --1 NonConvexFlowBlock_status(diesel_genset_bus_electricity_2) +-1 NonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_2) <= 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_0)_: From 71022830948dac0206560f49615f708a569258ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 15 Nov 2023 19:36:09 +0100 Subject: [PATCH 103/180] Update v0-5-2.rst Add OffsetConverter fix to WhatsNew --- docs/whatsnew/v0-5-2.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index 6859e1652..ac9b21ad2 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -22,6 +22,7 @@ Bug fixes Limit to costs that occur within the optimization horizon to prevent a bias towards investments happening earlier in the optimization horizon. * Fix bugs in multi-period documentation. +* Fix y intersect of OffsetConverter Testing ####### From ea8cead6bb02a200522950769c571c869b8f8484 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Fri, 17 Nov 2023 13:24:04 +0100 Subject: [PATCH 104/180] Fix / update storage investment examples --- .../storage_investment/v1_invest_optimize_all_technologies.py | 2 +- .../v2_invest_optimize_only_gas_and_storage.py | 2 +- .../v3_invest_optimize_only_storage_with_fossil_share.py | 2 +- .../v4_invest_optimize_all_technologies_with_fossil_share.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/storage_investment/v1_invest_optimize_all_technologies.py b/examples/storage_investment/v1_invest_optimize_all_technologies.py index 07a139778..8f3749fd5 100644 --- a/examples/storage_investment/v1_invest_optimize_all_technologies.py +++ b/examples/storage_investment/v1_invest_optimize_all_technologies.py @@ -191,7 +191,7 @@ def main(): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - nominal_value=solph.Investment(ep_costs=epc_storage), + nominal_storage_capacity=solph.Investment(ep_costs=epc_storage), ) energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas, storage) diff --git a/examples/storage_investment/v2_invest_optimize_only_gas_and_storage.py b/examples/storage_investment/v2_invest_optimize_only_gas_and_storage.py index b82cef608..00c251044 100644 --- a/examples/storage_investment/v2_invest_optimize_only_gas_and_storage.py +++ b/examples/storage_investment/v2_invest_optimize_only_gas_and_storage.py @@ -184,7 +184,7 @@ def main(): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - nominal_value=solph.Investment(ep_costs=epc_storage), + nominal_storage_capacity=solph.Investment(ep_costs=epc_storage), ) energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas, storage) diff --git a/examples/storage_investment/v3_invest_optimize_only_storage_with_fossil_share.py b/examples/storage_investment/v3_invest_optimize_only_storage_with_fossil_share.py index 7e8c9cc0c..f682620cf 100644 --- a/examples/storage_investment/v3_invest_optimize_only_storage_with_fossil_share.py +++ b/examples/storage_investment/v3_invest_optimize_only_storage_with_fossil_share.py @@ -194,7 +194,7 @@ def main(): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - nominal_value=solph.Investment(ep_costs=epc_storage), + nominal_storage_capacity=solph.Investment(ep_costs=epc_storage), ) energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas, storage) diff --git a/examples/storage_investment/v4_invest_optimize_all_technologies_with_fossil_share.py b/examples/storage_investment/v4_invest_optimize_all_technologies_with_fossil_share.py index d25af3f40..a9c3511c9 100644 --- a/examples/storage_investment/v4_invest_optimize_all_technologies_with_fossil_share.py +++ b/examples/storage_investment/v4_invest_optimize_all_technologies_with_fossil_share.py @@ -202,7 +202,7 @@ def main(): invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, - investment=solph.Investment(ep_costs=epc_storage), + nominal_storage_capacity=solph.Investment(ep_costs=epc_storage), ) energysystem.add(excess, gas_resource, wind, pv, demand, pp_gas, storage) From ac8b7028b741acc6958d0af342581f69158f889c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 22 Nov 2023 22:02:47 +0100 Subject: [PATCH 105/180] Draft simplified min_downtime_rule --- .../solph/flows/_non_convex_flow_block.py | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index ea5cec56c..be574751f 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -85,6 +85,12 @@ def _create_variables(self): """ m = self.parent_block() self.status = Var(self.NONCONVEX_FLOWS, m.TIMESTEPS, within=Binary) + for o, i in self.NONCONVEX_FLOWS: + if m.flows[o, i].nonconvex.initial_status is not None: + self.status[o, i, m.TIMESTEPS.at(1)] = m.flows[ + o, i + ].nonconvex.initial_status + self.status[o, i, m.TIMESTEPS.at(1)].fix() # `status_nominal` is a parameter which represents the # multiplication of a binary variable (`status`) @@ -469,24 +475,22 @@ def min_downtime_rule(_, i, o, t): """ Rule definition for min-downtime constraints of non-convex flows. """ - if self._time_step_allows_flexibility( - t, m.flows[i, o].nonconvex.max_up_down, m.TIMESTEPS.at(-1) - ): - expr = 0 - expr += ( - self.status[i, o, t - 1] - self.status[i, o, t] - ) * m.flows[i, o].nonconvex.minimum_downtime - expr += -m.flows[i, o].nonconvex.minimum_downtime - expr += sum( - self.status[i, o, t + d] - for d in range(0, m.flows[i, o].nonconvex.minimum_downtime) + expr = 0 + expr += ( + self.status[i, o, t] - self.status[i, o, t + 1] + ) * m.flows[i, o].nonconvex.minimum_downtime + expr += -m.flows[i, o].nonconvex.minimum_downtime + expr += sum( + self.status[i, o, d] + for d in range( + t, + min( + t + m.flows[i, o].nonconvex.minimum_downtime, + m.TIMESTEPS.at(-1), + ), ) - return expr <= 0 - else: - expr = 0 - expr += self.status[i, o, t] - expr += -m.flows[i, o].nonconvex.initial_status - return expr == 0 + ) + return expr <= 0 return Constraint( self.MINDOWNTIMEFLOWS, m.TIMESTEPS, rule=min_downtime_rule From 2f09a60a2a9c61ff0bd206b221529e8147f34454 Mon Sep 17 00:00:00 2001 From: "a.giannitelli" Date: Fri, 24 Nov 2023 12:36:26 +0100 Subject: [PATCH 106/180] limit t for constraint and update uptime_rule --- .../solph/flows/_non_convex_flow_block.py | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index be574751f..0a45a3fa5 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -475,22 +475,25 @@ def min_downtime_rule(_, i, o, t): """ Rule definition for min-downtime constraints of non-convex flows. """ - expr = 0 - expr += ( - self.status[i, o, t] - self.status[i, o, t + 1] - ) * m.flows[i, o].nonconvex.minimum_downtime - expr += -m.flows[i, o].nonconvex.minimum_downtime - expr += sum( - self.status[i, o, d] - for d in range( - t, - min( - t + m.flows[i, o].nonconvex.minimum_downtime, - m.TIMESTEPS.at(-1), - ), + if t < m.TIMESTEPS.at(-1): + expr = 0 + expr += ( + self.status[i, o, t] - self.status[i, o, t + 1] + ) * m.flows[i, o].nonconvex.minimum_downtime + expr += -m.flows[i, o].nonconvex.minimum_downtime + expr += sum( + self.status[i, o, d] + for d in range( + t, + min( + t + m.flows[i, o].nonconvex.minimum_downtime, + m.TIMESTEPS.at(-1), + ), + ) ) - ) - return expr <= 0 + return expr <= 0 + else: + return Constraint.Skip return Constraint( self.MINDOWNTIMEFLOWS, m.TIMESTEPS, rule=min_downtime_rule @@ -518,23 +521,18 @@ def _min_uptime_rule(_, i, o, t): """ Rule definition for min-uptime constraints of non-convex flows. """ - if self._time_step_allows_flexibility( - t, m.flows[i, o].nonconvex.max_up_down, m.TIMESTEPS.at(-1) - ): + if t < m.TIMESTEPS.at(-1): expr = 0 expr += ( - self.status[i, o, t] - self.status[i, o, t - 1] + self.status[i, o, t +1] - self.status[i, o, t] ) * m.flows[i, o].nonconvex.minimum_uptime expr += -sum( - self.status[i, o, t + u] - for u in range(0, m.flows[i, o].nonconvex.minimum_uptime) + self.status[i, o, u] + for u in range(t, min(t+ m.flows[i, o].nonconvex.minimum_uptime, m.TIMESTEPS.at(-1))) ) return expr <= 0 else: - expr = 0 - expr += self.status[i, o, t] - expr += -m.flows[i, o].nonconvex.initial_status - return expr == 0 + return Constraint.Skip return Constraint( self.MINUPTIMEFLOWS, m.TIMESTEPS, rule=_min_uptime_rule From bb1ee0c95ebb082010172a4fb06a457fc04b798e Mon Sep 17 00:00:00 2001 From: "a.giannitelli" Date: Fri, 24 Nov 2023 12:36:36 +0100 Subject: [PATCH 107/180] constraint-test --- tests/lp_files/min_max_runtime.lp | 49 ++++++++++++------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/tests/lp_files/min_max_runtime.lp b/tests/lp_files/min_max_runtime.lp index 5bd20f147..8e976935c 100644 --- a/tests/lp_files/min_max_runtime.lp +++ b/tests/lp_files/min_max_runtime.lp @@ -28,8 +28,7 @@ c_e_BusBlock_balance(Bus_T_0_2)_: c_e_NonConvexFlowBlock_status_nominal_constraint(cheap_plant_min_down_constraints_Bus_T_0)_: +1 NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_0) --10 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -= 0 += 20 c_e_NonConvexFlowBlock_status_nominal_constraint(cheap_plant_min_down_constraints_Bus_T_1)_: +1 NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_1) @@ -73,14 +72,12 @@ c_u_NonConvexFlowBlock_max(cheap_plant_min_down_constraints_Bus_T_0_2)_: c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_0) -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -<= 2 +<= 0 c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_1) --1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -<= 0 +<= 2 c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_2) @@ -90,14 +87,12 @@ c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_2)_ c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_0) --1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -<= -2 +<= 0 c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_1) -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -<= 0 +<= -2 c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_2) @@ -105,29 +100,23 @@ c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_2) -1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) <= 0 -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -= 2 - -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_1)_: +c_u_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_0)_: +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -= 2 - -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -= 2 +<= 6 -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -= 2 +c_u_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_1)_: +-3 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) ++2 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) +<= 0 -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -= 2 +c_u_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_0)_: +-3 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) +<= -6 -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -= 2 +c_u_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_1)_: ++5 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) +-4 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) +<= 4 bounds 0 <= flow(cheap_plant_min_down_constraints_Bus_T_0_0) <= 10.0 @@ -140,7 +129,6 @@ bounds 0 <= NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_1) <= 1 0 <= NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_2) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_0) <= +inf - 0 <= NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_1) <= +inf 0 <= NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_2) <= +inf @@ -152,7 +140,6 @@ binary NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_0) NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_1) NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_2) - NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) end From 470a1a03951acbe3004384090f8730f80c759bab Mon Sep 17 00:00:00 2001 From: michel Date: Fri, 24 Nov 2023 14:34:12 +0100 Subject: [PATCH 108/180] Improved file not found error, typo, added comment for structure, removed unclear part of comment, added one explanation for didactic purposes --- examples/basic_example/basic_example.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/basic_example/basic_example.py b/examples/basic_example/basic_example.py index c35aca98f..76ca8a4d0 100644 --- a/examples/basic_example/basic_example.py +++ b/examples/basic_example/basic_example.py @@ -90,7 +90,7 @@ def main(): try: data = pd.read_csv(filename) except FileNotFoundError: - msg = "Data file not found: {0}. Only one value used!" + msg = "Data file not found: {0}. Values for only one timestep created for usage!" warnings.warn(msg.format(filename), UserWarning) data = pd.DataFrame({"pv": [0.3], "wind": [0.6], "demand_el": [500]}) @@ -109,12 +109,13 @@ def main(): logging.info("Initialize the energy system") date_time_index = create_time_index(2012, number=number_of_time_steps) + # create the energysystem and assign the time index energysystem = EnergySystem( timeindex=date_time_index, infer_last_interval=False ) ########################################################################## - # Create oemof object + # Create oemof objects ########################################################################## logging.info("Create oemof objects") @@ -134,7 +135,7 @@ def main(): # create excess component for the electricity bus to allow overproduction energysystem.add(cmp.Sink(label="excess_bel", inputs={bel: flows.Flow()})) - # create source object representing the gas commodity (annual limit) + # create source object representing the gas commodity energysystem.add( cmp.Source( label="rgas", @@ -159,6 +160,7 @@ def main(): ) # create simple sink object representing the electrical demand + # nominal_value is here set to 1 because demand_el is not a normalised series energysystem.add( cmp.Sink( label="demand", From 0b0dd3f24400c2149978a02324e89af80c14d3e3 Mon Sep 17 00:00:00 2001 From: michel Date: Fri, 24 Nov 2023 14:44:10 +0100 Subject: [PATCH 109/180] Improved file not found error, typo, added comment for structure, removed unclear part of comment, added one explanation for didactic purposes --- examples/basic_example/basic_example.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/basic_example/basic_example.py b/examples/basic_example/basic_example.py index 76ca8a4d0..d8e6d7b12 100644 --- a/examples/basic_example/basic_example.py +++ b/examples/basic_example/basic_example.py @@ -90,7 +90,7 @@ def main(): try: data = pd.read_csv(filename) except FileNotFoundError: - msg = "Data file not found: {0}. Values for only one timestep created for usage!" + msg = "Data file not found: {0}. Values for one timestep created!" warnings.warn(msg.format(filename), UserWarning) data = pd.DataFrame({"pv": [0.3], "wind": [0.6], "demand_el": [500]}) @@ -160,7 +160,7 @@ def main(): ) # create simple sink object representing the electrical demand - # nominal_value is here set to 1 because demand_el is not a normalised series + # nominal_value is set to 1 because demand_el is not a normalised series energysystem.add( cmp.Sink( label="demand", From c2175a927c68e49ad6805b8cc39eecdbf4dec9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 24 Nov 2023 16:17:03 +0100 Subject: [PATCH 110/180] Adhere to Black --- src/oemof/solph/flows/_non_convex_flow_block.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index 0a45a3fa5..6858ac677 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -521,14 +521,20 @@ def _min_uptime_rule(_, i, o, t): """ Rule definition for min-uptime constraints of non-convex flows. """ - if t < m.TIMESTEPS.at(-1): + if t < m.TIMESTEPS.at(-1): expr = 0 expr += ( - self.status[i, o, t +1] - self.status[i, o, t] + self.status[i, o, t + 1] - self.status[i, o, t] ) * m.flows[i, o].nonconvex.minimum_uptime expr += -sum( self.status[i, o, u] - for u in range(t, min(t+ m.flows[i, o].nonconvex.minimum_uptime, m.TIMESTEPS.at(-1))) + for u in range( + t, + min( + t + m.flows[i, o].nonconvex.minimum_uptime, + m.TIMESTEPS.at(-1), + ), + ) ) return expr <= 0 else: From b12a24f4e5c9d6626bf5e115b624b1ec32beac3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 24 Nov 2023 16:44:05 +0100 Subject: [PATCH 111/180] Remove unused code --- src/oemof/solph/flows/_non_convex_flow_block.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index 6858ac677..fea5a0a8f 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -447,10 +447,6 @@ def _inactivity_costs(self): return inactivity_costs - @staticmethod - def _time_step_allows_flexibility(t, max_up_down, last_step): - return max_up_down <= t <= last_step - max_up_down - def _min_downtime_constraint(self): r""" .. math:: From b9aa489c155f818e30a4b2ade64adecbb6c33d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 27 Nov 2023 14:37:44 +0100 Subject: [PATCH 112/180] Fix activity status in initial steps This allows to go back to the indexing we used before. --- src/oemof/solph/_options.py | 2 ++ src/oemof/solph/flows/_non_convex_flow_block.py | 15 +++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index b57c153d6..e1720ead2 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -247,6 +247,8 @@ def __init__( for attribute, value in custom_attributes.items(): setattr(self, attribute, value) + self.first_flexible_timestep = max(minimum_uptime, minimum_downtime) + @property def max_up_down(self): """Return maximum of minimum_uptime and minimum_downtime. diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index fea5a0a8f..100f4ea91 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -87,10 +87,9 @@ def _create_variables(self): self.status = Var(self.NONCONVEX_FLOWS, m.TIMESTEPS, within=Binary) for o, i in self.NONCONVEX_FLOWS: if m.flows[o, i].nonconvex.initial_status is not None: - self.status[o, i, m.TIMESTEPS.at(1)] = m.flows[ - o, i - ].nonconvex.initial_status - self.status[o, i, m.TIMESTEPS.at(1)].fix() + for t in range(0, m.flows[o, i].nonconvex.first_flexible_timestep): + self.status[o, i, t] = m.flows[o, i].nonconvex.initial_status + self.status[o, i, t].fix() # `status_nominal` is a parameter which represents the # multiplication of a binary variable (`status`) @@ -471,10 +470,10 @@ def min_downtime_rule(_, i, o, t): """ Rule definition for min-downtime constraints of non-convex flows. """ - if t < m.TIMESTEPS.at(-1): + if m.flows[i, o].nonconvex.first_flexible_timestep < t < m.TIMESTEPS.at(-1): expr = 0 expr += ( - self.status[i, o, t] - self.status[i, o, t + 1] + self.status[i, o, t - 1] - self.status[i, o, t] ) * m.flows[i, o].nonconvex.minimum_downtime expr += -m.flows[i, o].nonconvex.minimum_downtime expr += sum( @@ -517,10 +516,10 @@ def _min_uptime_rule(_, i, o, t): """ Rule definition for min-uptime constraints of non-convex flows. """ - if t < m.TIMESTEPS.at(-1): + if m.flows[i, o].nonconvex.first_flexible_timestep < t < m.TIMESTEPS.at(-1): expr = 0 expr += ( - self.status[i, o, t + 1] - self.status[i, o, t] + self.status[i, o, t] - self.status[i, o, t - 1] ) * m.flows[i, o].nonconvex.minimum_uptime expr += -sum( self.status[i, o, u] From da8f826692a0306e0af184602dca4f88073f0ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 27 Nov 2023 14:41:59 +0100 Subject: [PATCH 113/180] Adhere to Black --- .../solph/flows/_non_convex_flow_block.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index 100f4ea91..1f5dbe96e 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -87,8 +87,12 @@ def _create_variables(self): self.status = Var(self.NONCONVEX_FLOWS, m.TIMESTEPS, within=Binary) for o, i in self.NONCONVEX_FLOWS: if m.flows[o, i].nonconvex.initial_status is not None: - for t in range(0, m.flows[o, i].nonconvex.first_flexible_timestep): - self.status[o, i, t] = m.flows[o, i].nonconvex.initial_status + for t in range( + 0, m.flows[o, i].nonconvex.first_flexible_timestep + ): + self.status[o, i, t] = m.flows[ + o, i + ].nonconvex.initial_status self.status[o, i, t].fix() # `status_nominal` is a parameter which represents the @@ -470,7 +474,11 @@ def min_downtime_rule(_, i, o, t): """ Rule definition for min-downtime constraints of non-convex flows. """ - if m.flows[i, o].nonconvex.first_flexible_timestep < t < m.TIMESTEPS.at(-1): + if ( + m.flows[i, o].nonconvex.first_flexible_timestep + < t + < m.TIMESTEPS.at(-1) + ): expr = 0 expr += ( self.status[i, o, t - 1] - self.status[i, o, t] @@ -516,7 +524,11 @@ def _min_uptime_rule(_, i, o, t): """ Rule definition for min-uptime constraints of non-convex flows. """ - if m.flows[i, o].nonconvex.first_flexible_timestep < t < m.TIMESTEPS.at(-1): + if ( + m.flows[i, o].nonconvex.first_flexible_timestep + < t + < m.TIMESTEPS.at(-1) + ): expr = 0 expr += ( self.status[i, o, t] - self.status[i, o, t - 1] From 70c3b61cbfa45882bbff3fed9c02f9f5f307728e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Tue, 28 Nov 2023 20:51:14 +0100 Subject: [PATCH 114/180] Set first flexible time step of NonConvexFlow based on initial status The old implementation lead to unwanted situations. E.g. a Flow with `initial_status=0` forcibly off for more time steps than `minimum_downtime` if the the `minimum_uptime` was bigger. --- src/oemof/solph/_options.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index e1720ead2..16a96ad69 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -247,7 +247,10 @@ def __init__( for attribute, value in custom_attributes.items(): setattr(self, attribute, value) - self.first_flexible_timestep = max(minimum_uptime, minimum_downtime) + if initial_status == 0: + self.first_flexible_timestep = minimum_downtime + else: + self.first_flexible_timestep = minimum_uptime @property def max_up_down(self): From 69b66e989a69eb1b93f1c2d25a2c8cf16dd96c97 Mon Sep 17 00:00:00 2001 From: "Julian.Endres" Date: Wed, 29 Nov 2023 15:25:43 +0100 Subject: [PATCH 115/180] Remove duplicated discounting The discounting is already taken care of by the list comprehension above. As it discount starting with the temporal distance of optimization start and investment period. --- src/oemof/solph/flows/_investment_flow_block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index a8d795ce7..5691e0bbc 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -1026,7 +1026,7 @@ def _objective_expression(self): m.es.periods_years[p], range_limit, ) - ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) + ) for i, o in self.EXISTING_INVESTFLOWS: if m.flows[i, o].investment.fixed_costs[0] is not None: From f74118c6252424c33a9aa3c4f559617f758c5026 Mon Sep 17 00:00:00 2001 From: "Julian.Endres" Date: Wed, 29 Nov 2023 15:30:18 +0100 Subject: [PATCH 116/180] Add changes --- docs/whatsnew/v0-5-2.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index ac9b21ad2..3b7963c0f 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -23,6 +23,7 @@ Bug fixes bias towards investments happening earlier in the optimization horizon. * Fix bugs in multi-period documentation. * Fix y intersect of OffsetConverter +* Fix duplicated discounting of fixed costs for multi-period investment Testing ####### From 32e62520ce753aececd683779294b5c11fdf6260 Mon Sep 17 00:00:00 2001 From: Johannes Kochems Date: Wed, 29 Nov 2023 16:21:05 +0100 Subject: [PATCH 117/180] Fix double discounting for storage and SinkDSM TODO: Adjust tests! --- src/oemof/solph/components/_generic_storage.py | 2 +- src/oemof/solph/components/experimental/_sink_dsm.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index 352fd64db..adfadd2b7 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -1869,7 +1869,7 @@ def _objective_expression(self): m.es.periods_years[p], range_limit, ) - ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) + ) for n in self.EXISTING_INVESTSTORAGES: if n.investment.fixed_costs[0] is not None: diff --git a/src/oemof/solph/components/experimental/_sink_dsm.py b/src/oemof/solph/components/experimental/_sink_dsm.py index 9d9a0c758..60fdb4138 100644 --- a/src/oemof/solph/components/experimental/_sink_dsm.py +++ b/src/oemof/solph/components/experimental/_sink_dsm.py @@ -1447,7 +1447,7 @@ def _objective_expression(self): m.es.periods_years[p], range_limit, ) - ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) + ) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: @@ -3301,7 +3301,7 @@ def _objective_expression(self): m.es.periods_years[p], range_limit, ) - ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) + ) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: @@ -5800,7 +5800,7 @@ def _objective_expression(self): m.es.periods_years[p], range_limit, ) - ) * (1 + m.discount_rate) ** (-m.es.periods_years[p]) + ) for g in self.EXISTING_INVESTDSM: if g.investment.fixed_costs[0] is not None: From b616c525323e10101c48beac2ed947696508e93f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 29 Nov 2023 20:21:35 +0100 Subject: [PATCH 118/180] Deprecate NonConvex.max_up_down --- src/oemof/solph/_options.py | 6 ++++++ .../test_solph/test_options/test_non_convex.py | 15 +++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index 16a96ad69..a0edd479d 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -13,6 +13,7 @@ SPDX-License-Identifier: MIT """ +from warnings import warn from oemof.solph._plumbing import sequence @@ -259,4 +260,9 @@ def max_up_down(self): The maximum of both is used to set the initial status for this number of time steps within the edge regions. """ + warn( + "Use of max_up_down is deprecated. " + "The attribute will be deleted in a future version.", + FutureWarning, + ) return max(self.minimum_uptime, self.minimum_downtime) diff --git a/tests/test_scripts/test_solph/test_options/test_non_convex.py b/tests/test_scripts/test_solph/test_options/test_non_convex.py index 9a7308cdb..066b4f1e8 100644 --- a/tests/test_scripts/test_solph/test_options/test_non_convex.py +++ b/tests/test_scripts/test_solph/test_options/test_non_convex.py @@ -9,6 +9,8 @@ SPDX-License-Identifier: MIT """ +import pytest + from oemof.solph import NonConvex @@ -29,17 +31,22 @@ def test_max_up_down(): minimum_uptime=5, minimum_downtime=4, ) - assert non_convex_object1.max_up_down == 5 + + with pytest.warns(FutureWarning): + assert non_convex_object1.max_up_down == 5 non_convex_object1 = NonConvex( minimum_downtime=4, ) - assert non_convex_object1.max_up_down == 4 + with pytest.warns(FutureWarning): + assert non_convex_object1.max_up_down == 4 non_convex_object1 = NonConvex( minimum_uptime=5, ) - assert non_convex_object1.max_up_down == 5 + with pytest.warns(FutureWarning): + assert non_convex_object1.max_up_down == 5 non_convex_object1 = NonConvex() - assert non_convex_object1.max_up_down == 0 + with pytest.warns(FutureWarning): + assert non_convex_object1.max_up_down == 0 From 00e98257f250d42a8c5e278b38d727ed6bc24f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 29 Nov 2023 20:21:57 +0100 Subject: [PATCH 119/180] Fix invalid initial status in constraint_test --- tests/constraint_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/constraint_tests.py b/tests/constraint_tests.py index b3a186a36..2f9e8b5b1 100644 --- a/tests/constraint_tests.py +++ b/tests/constraint_tests.py @@ -1227,7 +1227,7 @@ def test_min_max_runtime(self): nonconvex=solph.NonConvex( minimum_downtime=4, minimum_uptime=2, - initial_status=2, + initial_status=1, startup_costs=5, shutdown_costs=7, ), From 111f1e1218e85567e960c5a1417ffb8f118a4c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 29 Nov 2023 20:24:51 +0100 Subject: [PATCH 120/180] Explain need for braching in _min_uptime_rule --- src/oemof/solph/flows/_non_convex_flow_block.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index 1f5dbe96e..9cfd9caae 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -479,6 +479,9 @@ def min_downtime_rule(_, i, o, t): < t < m.TIMESTEPS.at(-1) ): + # We have a 2D matrix of constraints, + # so testing is easier then just calling the rule for valid t. + expr = 0 expr += ( self.status[i, o, t - 1] - self.status[i, o, t] @@ -529,6 +532,8 @@ def _min_uptime_rule(_, i, o, t): < t < m.TIMESTEPS.at(-1) ): + # We have a 2D matrix of constraints, + # so testing is easier then just calling the rule for valid t. expr = 0 expr += ( self.status[i, o, t] - self.status[i, o, t - 1] From fe05c56510c0ad201f2d6a90ff2fba61a5e2acc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 29 Nov 2023 21:02:34 +0100 Subject: [PATCH 121/180] Add NonConvex up-/ downtime fix to WhatsNew --- docs/whatsnew/v0-5-2.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index ac9b21ad2..9fbae21a0 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -23,6 +23,7 @@ Bug fixes bias towards investments happening earlier in the optimization horizon. * Fix bugs in multi-period documentation. * Fix y intersect of OffsetConverter +* Fix minimum uptime being relevant for initial downtime (and vice versa). Testing ####### From 7f211748fcde3b8989209c0209db6b03a9e3a2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 30 Nov 2023 20:43:17 +0100 Subject: [PATCH 122/180] Let minimum_uptime and minimum_downtime be series This also means that NonConvex.max_up_down has to be deleted, as it's not meaningful for two series. --- src/oemof/solph/_options.py | 22 +++------------ .../solph/flows/_non_convex_flow_block.py | 18 ++++++------ .../test_options/test_non_convex.py | 28 ------------------- 3 files changed, 13 insertions(+), 55 deletions(-) diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index a0edd479d..d79c58fcb 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -233,8 +233,8 @@ def __init__( custom_attributes = {} self.initial_status = initial_status - self.minimum_uptime = minimum_uptime - self.minimum_downtime = minimum_downtime + self.minimum_uptime = sequence(minimum_uptime) + self.minimum_downtime = sequence(minimum_downtime) self.maximum_startups = maximum_startups self.maximum_shutdowns = maximum_shutdowns @@ -249,20 +249,6 @@ def __init__( setattr(self, attribute, value) if initial_status == 0: - self.first_flexible_timestep = minimum_downtime + self.first_flexible_timestep = self.minimum_downtime[0] else: - self.first_flexible_timestep = minimum_uptime - - @property - def max_up_down(self): - """Return maximum of minimum_uptime and minimum_downtime. - - The maximum of both is used to set the initial status for this - number of time steps within the edge regions. - """ - warn( - "Use of max_up_down is deprecated. " - "The attribute will be deleted in a future version.", - FutureWarning, - ) - return max(self.minimum_uptime, self.minimum_downtime) + self.first_flexible_timestep = self.minimum_uptime[0] diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index 9cfd9caae..db65335dc 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -182,10 +182,10 @@ def _sets_for_non_convex_flows(self, group): `maximum_shutdowns` being not None. MINUPTIMEFLOWS A subset of set NONCONVEX_FLOWS with the attribute - `minimum_uptime` being not None. + `minimum_uptime` being > 0. MINDOWNTIMEFLOWS A subset of set NONCONVEX_FLOWS with the attribute - `minimum_downtime` being not None. + `minimum_downtime` being > 0. POSITIVE_GRADIENT_FLOWS A subset of set NONCONVEX_FLOWS with the attribute `positive_gradient` being not None. @@ -230,14 +230,14 @@ def _sets_for_non_convex_flows(self, group): initialize=[ (g[0], g[1]) for g in group - if g[2].nonconvex.minimum_uptime > 0 + if max(g[2].nonconvex.minimum_uptime) > 0 ] ) self.MINDOWNTIMEFLOWS = Set( initialize=[ (g[0], g[1]) for g in group - if g[2].nonconvex.minimum_downtime > 0 + if max(g[2].nonconvex.minimum_downtime) > 0 ] ) self.NEGATIVE_GRADIENT_FLOWS = Set( @@ -485,14 +485,14 @@ def min_downtime_rule(_, i, o, t): expr = 0 expr += ( self.status[i, o, t - 1] - self.status[i, o, t] - ) * m.flows[i, o].nonconvex.minimum_downtime - expr += -m.flows[i, o].nonconvex.minimum_downtime + ) * m.flows[i, o].nonconvex.minimum_downtime[t] + expr += -m.flows[i, o].nonconvex.minimum_downtime[t] expr += sum( self.status[i, o, d] for d in range( t, min( - t + m.flows[i, o].nonconvex.minimum_downtime, + t + m.flows[i, o].nonconvex.minimum_downtime[t], m.TIMESTEPS.at(-1), ), ) @@ -537,13 +537,13 @@ def _min_uptime_rule(_, i, o, t): expr = 0 expr += ( self.status[i, o, t] - self.status[i, o, t - 1] - ) * m.flows[i, o].nonconvex.minimum_uptime + ) * m.flows[i, o].nonconvex.minimum_uptime[t] expr += -sum( self.status[i, o, u] for u in range( t, min( - t + m.flows[i, o].nonconvex.minimum_uptime, + t + m.flows[i, o].nonconvex.minimum_uptime[t], m.TIMESTEPS.at(-1), ), ) diff --git a/tests/test_scripts/test_solph/test_options/test_non_convex.py b/tests/test_scripts/test_solph/test_options/test_non_convex.py index 066b4f1e8..f43df5fc5 100644 --- a/tests/test_scripts/test_solph/test_options/test_non_convex.py +++ b/tests/test_scripts/test_solph/test_options/test_non_convex.py @@ -9,8 +9,6 @@ SPDX-License-Identifier: MIT """ -import pytest - from oemof.solph import NonConvex @@ -24,29 +22,3 @@ def test_custom_attribute(): assert non_convex_object.first_attribute is True assert non_convex_object.second_attribute == 5 - - -def test_max_up_down(): - non_convex_object1 = NonConvex( - minimum_uptime=5, - minimum_downtime=4, - ) - - with pytest.warns(FutureWarning): - assert non_convex_object1.max_up_down == 5 - - non_convex_object1 = NonConvex( - minimum_downtime=4, - ) - with pytest.warns(FutureWarning): - assert non_convex_object1.max_up_down == 4 - - non_convex_object1 = NonConvex( - minimum_uptime=5, - ) - with pytest.warns(FutureWarning): - assert non_convex_object1.max_up_down == 5 - - non_convex_object1 = NonConvex() - with pytest.warns(FutureWarning): - assert non_convex_object1.max_up_down == 0 From d72a590dfde87e2bbe25b4da40415a139dcacb66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 30 Nov 2023 20:49:52 +0100 Subject: [PATCH 123/180] Remove unused import --- src/oemof/solph/_options.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index d79c58fcb..db0c56f0b 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -13,8 +13,6 @@ SPDX-License-Identifier: MIT """ -from warnings import warn - from oemof.solph._plumbing import sequence From 9312c7cba125ec5f8dfae256b308606d373fa8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 30 Nov 2023 22:10:15 +0100 Subject: [PATCH 124/180] Let len(sequence(0)) == 1 Initialising the sequence as non-empty allows for using it in e.g. `max(sequence(value)) == value` --- src/oemof/solph/_plumbing.py | 4 ++-- tests/test_plumbing.py | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/test_plumbing.py diff --git a/src/oemof/solph/_plumbing.py b/src/oemof/solph/_plumbing.py index 460a46aa6..806cf9507 100644 --- a/src/oemof/solph/_plumbing.py +++ b/src/oemof/solph/_plumbing.py @@ -61,7 +61,7 @@ class _Sequence(UserList): -------- >>> s = _Sequence(default=42) >>> len(s) - 0 + 1 >>> s[1] 42 >>> s[2] @@ -79,7 +79,7 @@ class _Sequence(UserList): def __init__(self, *args, **kwargs): self.default = kwargs["default"] self.default_changed = False - self.highest_index = -1 + self.highest_index = 0 super().__init__(*args) def __getitem__(self, key): diff --git a/tests/test_plumbing.py b/tests/test_plumbing.py new file mode 100644 index 000000000..8406a1421 --- /dev/null +++ b/tests/test_plumbing.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 - + +"""Testing the class NonConvex. + +SPDX-FileCopyrightText: Patrik Schönfeldt + +SPDX-License-Identifier: MIT +""" +import pytest + +from oemof.solph._plumbing import sequence + +def test_sequence(): + seq0 = sequence(0) + assert seq0[0] == 0 + assert len(seq0) == 1 + + assert seq0[10] == 0 + assert len(seq0) == 11 + + assert max(seq0) == 0 + + seq10 = sequence(10) + assert max(seq10) == 10 + + assert seq10[0] == 10 + assert len(seq10) == 1 + + assert seq10[10] == 10 + assert len(seq10) == 11 + + seq12 = sequence([1, 3]) + assert max(seq12) == 3 + assert seq12[0] == 1 + assert seq12[1] == 3 + + with pytest.raises(IndexError): + seq12[2] From 1a938718d92a0602429f412436750b493dc22ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 30 Nov 2023 22:11:27 +0100 Subject: [PATCH 125/180] Adhere to Black --- tests/test_plumbing.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_plumbing.py b/tests/test_plumbing.py index 8406a1421..2c7a54a37 100644 --- a/tests/test_plumbing.py +++ b/tests/test_plumbing.py @@ -10,6 +10,7 @@ from oemof.solph._plumbing import sequence + def test_sequence(): seq0 = sequence(0) assert seq0[0] == 0 From 2b30979b2942cf22dfb7f47f60794c95f745e883 Mon Sep 17 00:00:00 2001 From: Antonella Giannitelli <45421712+AntonellaConsolinno@users.noreply.github.com> Date: Fri, 1 Dec 2023 06:22:56 +0100 Subject: [PATCH 126/180] Update documenation --- src/oemof/solph/_options.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index db0c56f0b..b6f4165c6 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -183,11 +183,11 @@ class NonConvex: from the actual output. inactivity_costs : numeric (iterable or scalar) Costs associated with not operating the flow. - minimum_uptime : numeric (1 or positive integer) + minimum_uptime : numeric or list of numeric (1 or positive integer) Minimum number of time steps that a flow must be greater then its minimum flow after startup. Be aware that minimum up and downtimes can contradict each other and may lead to infeasible problems. - minimum_downtime : numeric (1 or positive integer) + minimum_downtime : numeric or list of numeric (1 or positive integer) Minimum number of time steps a flow is forced to zero after shutting down. Be aware that minimum up and downtimes can contradict each other and may to infeasible problems. @@ -198,12 +198,12 @@ class NonConvex: initial_status : numeric (0 or 1) Integer value indicating the status of the flow in the first time step (0 = off, 1 = on). For minimum up and downtimes, the initial status - is set for the respective values in the edge regions e.g. if a - minimum uptime of four timesteps is defined, the initial status is - fixed for the four first and last timesteps of the optimization period. - If both, up and downtimes are defined, the initial status is set for - the maximum of both e.g. for six timesteps if a minimum downtime of - six timesteps is defined besides a four timestep minimum uptime. + is set for the respective values in the beginning e.g. if a + minimum uptime of four timesteps is defined and the initial status is + set to one, the initial status is fixed for the four first timesteps + of the optimization period. Otherwise if the initial status is set to + zero and the first timesteps are fixed for the number of minimum + downtime steps. negative_gradient_limit : numeric (iterable, scalar or None) the normed *upper bound* on the positive difference (`flow[t-1] < flow[t]`) of two consecutive flow values. From 951ebbb71d28b88623e8e1b0b02ef15884de785a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 1 Dec 2023 09:48:47 +0100 Subject: [PATCH 127/180] Remove trailing whitespace --- src/oemof/solph/_options.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/oemof/solph/_options.py b/src/oemof/solph/_options.py index b6f4165c6..ae0cecd22 100644 --- a/src/oemof/solph/_options.py +++ b/src/oemof/solph/_options.py @@ -199,10 +199,10 @@ class NonConvex: Integer value indicating the status of the flow in the first time step (0 = off, 1 = on). For minimum up and downtimes, the initial status is set for the respective values in the beginning e.g. if a - minimum uptime of four timesteps is defined and the initial status is - set to one, the initial status is fixed for the four first timesteps - of the optimization period. Otherwise if the initial status is set to - zero and the first timesteps are fixed for the number of minimum + minimum uptime of four timesteps is defined and the initial status is + set to one, the initial status is fixed for the four first timesteps + of the optimization period. Otherwise if the initial status is set to + zero and the first timesteps are fixed for the number of minimum downtime steps. negative_gradient_limit : numeric (iterable, scalar or None) the normed *upper bound* on the positive difference From 42a2b80dfd857416eb6a794a0996118916f58e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 1 Dec 2023 09:51:56 +0100 Subject: [PATCH 128/180] Workaround useless statement message The "fixed" test just tests if an error is risen on access. Saving the (not existing) result to a variable should avoid code quality bots from complaining. --- tests/test_plumbing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_plumbing.py b/tests/test_plumbing.py index 2c7a54a37..4ed99c110 100644 --- a/tests/test_plumbing.py +++ b/tests/test_plumbing.py @@ -36,4 +36,4 @@ def test_sequence(): assert seq12[1] == 3 with pytest.raises(IndexError): - seq12[2] + _ = seq12[2] From 67511b1914743d9980251a6a305c214ce96ffb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 1 Dec 2023 10:04:44 +0100 Subject: [PATCH 129/180] Fix storage investment test I do not get why this does not fail in dev, but I am taking the freedom to alter it in this branch so that it does not cause problems. --- tests/constraint_tests.py | 2 +- tests/lp_files/storage_invest_1_fixed_losses.lp | 2 +- tests/multi_period_constraint_tests.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/constraint_tests.py b/tests/constraint_tests.py index 2f9e8b5b1..4738fe8d0 100644 --- a/tests/constraint_tests.py +++ b/tests/constraint_tests.py @@ -520,7 +520,7 @@ def test_storage_invest_1_fixed_losses(self): inflow_conversion_factor=0.97, outflow_conversion_factor=0.86, nominal_storage_capacity=solph.Investment( - ep_costs=145, maximum=234 + ep_costs=145, minimum=1, maximum=234 ), ) self.energysystem.add(bel, storage) diff --git a/tests/lp_files/storage_invest_1_fixed_losses.lp b/tests/lp_files/storage_invest_1_fixed_losses.lp index c6c2ce6db..2ab9c0173 100644 --- a/tests/lp_files/storage_invest_1_fixed_losses.lp +++ b/tests/lp_files/storage_invest_1_fixed_losses.lp @@ -153,7 +153,7 @@ bounds 0 <= flow(storage1_electricityBus_0_0) <= +inf 0 <= flow(storage1_electricityBus_0_1) <= +inf 0 <= flow(storage1_electricityBus_0_2) <= +inf - 0 <= GenericInvestmentStorageBlock_invest(storage1_0) <= 234 + 1 <= GenericInvestmentStorageBlock_invest(storage1_0) <= 234 0 <= InvestmentFlowBlock_total(electricityBus_storage1_0) <= +inf 0 <= InvestmentFlowBlock_invest(electricityBus_storage1_0) <= +inf 0 <= InvestmentFlowBlock_total(storage1_electricityBus_0) <= +inf diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index e2992856f..0b1e4bfd1 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -661,6 +661,7 @@ def test_storage_invest_1_fixed_losses(self): lifetime_outflow=40, nominal_storage_capacity=solph.Investment( ep_costs=145, + minimum=1, maximum=234, lifetime=20, interest_rate=0.05, From 64f67e77d91c7ce4c65461cf264572e3bfc27200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 1 Dec 2023 10:21:54 +0100 Subject: [PATCH 130/180] Adjust min_max_runtime test lp files The new formulation needs less constraints, so the constraint test needs to be adjusted. --- tests/lp_files/min_max_runtime.lp | 37 ++------- .../lp_files/min_max_runtime_multi_period.lp | 82 +++++-------------- 2 files changed, 27 insertions(+), 92 deletions(-) diff --git a/tests/lp_files/min_max_runtime.lp b/tests/lp_files/min_max_runtime.lp index 8e976935c..cde473813 100644 --- a/tests/lp_files/min_max_runtime.lp +++ b/tests/lp_files/min_max_runtime.lp @@ -28,12 +28,11 @@ c_e_BusBlock_balance(Bus_T_0_2)_: c_e_NonConvexFlowBlock_status_nominal_constraint(cheap_plant_min_down_constraints_Bus_T_0)_: +1 NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_0) -= 20 += 10 c_e_NonConvexFlowBlock_status_nominal_constraint(cheap_plant_min_down_constraints_Bus_T_1)_: +1 NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_1) --10 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -= 0 += 10 c_e_NonConvexFlowBlock_status_nominal_constraint(cheap_plant_min_down_constraints_Bus_T_2)_: +1 NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_2) @@ -76,14 +75,12 @@ c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_0)_ c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_1) -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -<= 2 +<= 0 c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_2) --1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -<= 0 +<= 1 c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_0) @@ -91,32 +88,12 @@ c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_0) c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_1) --1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -<= -2 +<= 0 c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_2) -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -<= 0 - -c_u_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -<= 6 - -c_u_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_1)_: --3 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -+2 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -<= 0 - -c_u_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_0)_: --3 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -<= -6 - -c_u_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -+5 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) --4 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -<= 4 +<= -1 bounds 0 <= flow(cheap_plant_min_down_constraints_Bus_T_0_0) <= 10.0 @@ -130,7 +107,6 @@ bounds 0 <= NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_2) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_0) <= +inf 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_1) <= +inf - 0 <= NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_2) <= +inf 0 <= NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) <= 1 binary @@ -140,6 +116,5 @@ binary NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_0) NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_1) NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_2) - NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) end diff --git a/tests/lp_files/min_max_runtime_multi_period.lp b/tests/lp_files/min_max_runtime_multi_period.lp index 922976d9e..93438ffa9 100644 --- a/tests/lp_files/min_max_runtime_multi_period.lp +++ b/tests/lp_files/min_max_runtime_multi_period.lp @@ -49,13 +49,11 @@ c_e_BusBlock_balance(Bus_T_2_5)_: c_e_NonConvexFlowBlock_status_nominal_constraint(cheap_plant_min_down_constraints_Bus_T_0)_: +1 NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_0) --10 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -= 0 += 10 c_e_NonConvexFlowBlock_status_nominal_constraint(cheap_plant_min_down_constraints_Bus_T_1)_: +1 NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_1) --10 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -= 0 += 10 c_e_NonConvexFlowBlock_status_nominal_constraint(cheap_plant_min_down_constraints_Bus_T_2)_: +1 NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_2) @@ -139,20 +137,16 @@ c_u_NonConvexFlowBlock_max(cheap_plant_min_down_constraints_Bus_T_2_5)_: c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_0) -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -<= 1 +<= 0 c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_1) --1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) <= 0 c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_2) --1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -<= 0 +<= 1 c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_3)_: -1 NonConvexFlowBlock_startup(cheap_plant_min_down_constraints_Bus_T_3) @@ -174,20 +168,16 @@ c_u_NonConvexFlowBlock_startup_constr(cheap_plant_min_down_constraints_Bus_T_5)_ c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_0) --1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -<= -1 +<= 0 c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_1) -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) --1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) <= 0 c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_2) -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -<= 0 +<= -1 c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_3)_: -1 NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_3) @@ -207,53 +197,27 @@ c_u_NonConvexFlowBlock_shutdown_constr(cheap_plant_min_down_constraints_Bus_T_5) -1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_5) <= 0 -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -= 1 - -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -= 1 - -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -= 1 - -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_3)_: +c_u_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_3)_: +-2 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) -= 1 +-1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_4) +<= 0 -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_4)_: +c_u_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_4)_: +-2 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_4) -= 1 - -c_e_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_5)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_5) -= 1 - -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_0)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) -= 1 - -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_1)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) -= 1 - -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_2)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -= 1 - -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_3)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) -= 1 +<= 0 -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_4)_: +c_u_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_3)_: ++4 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) +-3 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_4) -= 1 +<= 4 -c_e_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_5)_: -+1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_5) -= 1 +c_u_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_4)_: ++4 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) +-3 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_4) +<= 4 bounds 0 <= flow(cheap_plant_min_down_constraints_Bus_T_0_0) <= 10.0 @@ -275,9 +239,7 @@ bounds 0 <= NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_4) <= 1 0 <= NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_5) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_0) <= +inf - 0 <= NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_1) <= +inf - 0 <= NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_2) <= +inf 0 <= NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) <= 1 0 <= NonConvexFlowBlock_status_nominal(cheap_plant_min_down_constraints_Bus_T_3) <= +inf @@ -299,8 +261,6 @@ binary NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_3) NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_4) NonConvexFlowBlock_shutdown(cheap_plant_min_down_constraints_Bus_T_5) - NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_0) - NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_1) NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_4) From 22abd387bea56a04623f61acf382c80824e2c188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 1 Dec 2023 10:29:18 +0100 Subject: [PATCH 131/180] Replace "0.0" by "0" in dsm test lp file I really do not get why this was not an issue before. (I know that Pyomo started "rounding" some time ago.) --- tests/lp_files/dsm_module_oemof_extended.lp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lp_files/dsm_module_oemof_extended.lp b/tests/lp_files/dsm_module_oemof_extended.lp index 3ebe9b458..7d2eda425 100644 --- a/tests/lp_files/dsm_module_oemof_extended.lp +++ b/tests/lp_files/dsm_module_oemof_extended.lp @@ -79,7 +79,7 @@ c_e_SinkDSMOemofBlock_dsm_sum_constraint(demand_dsm_0)_: +0.99 SinkDSMOemofBlock_dsm_up(demand_dsm_0) +0.99 SinkDSMOemofBlock_dsm_up(demand_dsm_1) -1 SinkDSMOemofBlock_dsm_do_shift(demand_dsm_1) -= 0.0 += 0 bounds 0 <= SinkDSMOemofBlock_dsm_do_shift(demand_dsm_0) <= +inf From 76989a0822809aeeabccddf16bc7a0f123751c85 Mon Sep 17 00:00:00 2001 From: "a.giannitelli" Date: Mon, 4 Dec 2023 10:22:56 +0100 Subject: [PATCH 132/180] iterate one more step uptime last timestep --- src/oemof/solph/flows/_non_convex_flow_block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index db65335dc..be9d73a71 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -544,7 +544,7 @@ def _min_uptime_rule(_, i, o, t): t, min( t + m.flows[i, o].nonconvex.minimum_uptime[t], - m.TIMESTEPS.at(-1), + len(m.TIMESTEPS), ), ) ) From 44639b6d2febcaeea4e84d5f7764e2d610f8ae2b Mon Sep 17 00:00:00 2001 From: "a.giannitelli" Date: Mon, 4 Dec 2023 10:32:55 +0100 Subject: [PATCH 133/180] iterate one more step downtime last timestep --- src/oemof/solph/flows/_non_convex_flow_block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oemof/solph/flows/_non_convex_flow_block.py b/src/oemof/solph/flows/_non_convex_flow_block.py index be9d73a71..89faa9320 100644 --- a/src/oemof/solph/flows/_non_convex_flow_block.py +++ b/src/oemof/solph/flows/_non_convex_flow_block.py @@ -493,7 +493,7 @@ def min_downtime_rule(_, i, o, t): t, min( t + m.flows[i, o].nonconvex.minimum_downtime[t], - m.TIMESTEPS.at(-1), + len(m.TIMESTEPS), ), ) ) From 5f0c400f66a1ab30869ff8f73c82cdc0a3120ff0 Mon Sep 17 00:00:00 2001 From: "Julian.Endres" Date: Tue, 5 Dec 2023 17:16:57 +0100 Subject: [PATCH 134/180] Remove comma --- src/oemof/solph/flows/_investment_flow_block.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 5691e0bbc..464f41ee8 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -1024,8 +1024,7 @@ def _objective_expression(self): * (1 + m.discount_rate) ** (-pp) for pp in range( m.es.periods_years[p], - range_limit, - ) + range_limit) ) for i, o in self.EXISTING_INVESTFLOWS: From e8e4956c765fa24af80ee593dc2cbcb5d39c4720 Mon Sep 17 00:00:00 2001 From: "Julian.Endres" Date: Tue, 5 Dec 2023 17:18:16 +0100 Subject: [PATCH 135/180] Adjust LP-files to `fixed` fixed costs discounting --- .../dsm_module_DIW_invest_multi_period.lp | 4 +- ...DIW_invest_multi_period_remaining_value.lp | 4 +- .../dsm_module_DLR_invest_multi_period.lp | 4 +- ...DLR_invest_multi_period_remaining_value.lp | 4 +- .../dsm_module_oemof_invest_multi_period.lp | 4 +- ...mof_invest_multi_period_remaining_value.lp | 4 +- tests/lp_files/multi_period_period_length.lp | 626 +++++++++--------- tests/lp_files/storage_invest_multi_period.lp | 6 +- 8 files changed, 328 insertions(+), 328 deletions(-) diff --git a/tests/lp_files/dsm_module_DIW_invest_multi_period.lp b/tests/lp_files/dsm_module_DIW_invest_multi_period.lp index 68ad9b43c..1ff5873d6 100644 --- a/tests/lp_files/dsm_module_DIW_invest_multi_period.lp +++ b/tests/lp_files/dsm_module_DIW_invest_multi_period.lp @@ -52,8 +52,8 @@ objective: +0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) +96.11687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) +76.46810240317063 SinkDSMDIWInvestmentBlock_invest(demand_dsm_0) -+49.710949277906536 SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) -+24.239842660236203 SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) ++50.47234572422055 SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) ++24.986309764465627 SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) s.t. diff --git a/tests/lp_files/dsm_module_DIW_invest_multi_period_remaining_value.lp b/tests/lp_files/dsm_module_DIW_invest_multi_period_remaining_value.lp index e8f35046c..c4783b7fe 100644 --- a/tests/lp_files/dsm_module_DIW_invest_multi_period_remaining_value.lp +++ b/tests/lp_files/dsm_module_DIW_invest_multi_period_remaining_value.lp @@ -52,8 +52,8 @@ objective: +0.9611687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_5_5) +96.11687812379853 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_5) +57.62165571222974 SinkDSMDIWInvestmentBlock_invest(demand_dsm_0) -+39.12361323621548 SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) -+23.087255832295018 SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) ++39.8850096825295 SinkDSMDIWInvestmentBlock_invest(demand_dsm_1) ++23.833722936524442 SinkDSMDIWInvestmentBlock_invest(demand_dsm_2) s.t. diff --git a/tests/lp_files/dsm_module_DLR_invest_multi_period.lp b/tests/lp_files/dsm_module_DLR_invest_multi_period.lp index 3fb7aa6fd..4bfd30471 100644 --- a/tests/lp_files/dsm_module_DLR_invest_multi_period.lp +++ b/tests/lp_files/dsm_module_DLR_invest_multi_period.lp @@ -58,8 +58,8 @@ objective: +0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) +96.11687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) +76.46810240317063 SinkDSMDLRInvestmentBlock_invest(demand_dsm_0) -+49.710949277906536 SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) -+24.239842660236203 SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) ++50.47234572422055 SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) ++24.986309764465627 SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) s.t. diff --git a/tests/lp_files/dsm_module_DLR_invest_multi_period_remaining_value.lp b/tests/lp_files/dsm_module_DLR_invest_multi_period_remaining_value.lp index d543924d8..2742536af 100644 --- a/tests/lp_files/dsm_module_DLR_invest_multi_period_remaining_value.lp +++ b/tests/lp_files/dsm_module_DLR_invest_multi_period_remaining_value.lp @@ -58,8 +58,8 @@ objective: +0.9611687812379853 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_2_5) +96.11687812379853 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_5) +57.62165571222974 SinkDSMDLRInvestmentBlock_invest(demand_dsm_0) -+39.12361323621548 SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) -+23.087255832295018 SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) ++39.8850096825295 SinkDSMDLRInvestmentBlock_invest(demand_dsm_1) ++23.833722936524442 SinkDSMDLRInvestmentBlock_invest(demand_dsm_2) s.t. diff --git a/tests/lp_files/dsm_module_oemof_invest_multi_period.lp b/tests/lp_files/dsm_module_oemof_invest_multi_period.lp index b92f80115..47a17847e 100644 --- a/tests/lp_files/dsm_module_oemof_invest_multi_period.lp +++ b/tests/lp_files/dsm_module_oemof_invest_multi_period.lp @@ -22,8 +22,8 @@ objective: +0.9611687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_5) +96.11687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_5) +76.46810240317063 SinkDSMOemofInvestmentBlock_invest(demand_dsm_0) -+49.710949277906536 SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) -+24.239842660236203 SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) ++50.47234572422055 SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) ++24.986309764465627 SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) s.t. diff --git a/tests/lp_files/dsm_module_oemof_invest_multi_period_remaining_value.lp b/tests/lp_files/dsm_module_oemof_invest_multi_period_remaining_value.lp index 0baff5cc8..5b31f8473 100644 --- a/tests/lp_files/dsm_module_oemof_invest_multi_period_remaining_value.lp +++ b/tests/lp_files/dsm_module_oemof_invest_multi_period_remaining_value.lp @@ -22,8 +22,8 @@ objective: +0.9611687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_5) +96.11687812379853 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_5) +57.62165571222974 SinkDSMOemofInvestmentBlock_invest(demand_dsm_0) -+39.12361323621548 SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) -+23.087255832295018 SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) ++39.8850096825295 SinkDSMOemofInvestmentBlock_invest(demand_dsm_1) ++23.833722936524442 SinkDSMOemofInvestmentBlock_invest(demand_dsm_2) s.t. diff --git a/tests/lp_files/multi_period_period_length.lp b/tests/lp_files/multi_period_period_length.lp index 8f7edb5d0..58dd7db26 100644 --- a/tests/lp_files/multi_period_period_length.lp +++ b/tests/lp_files/multi_period_period_length.lp @@ -3,14 +3,6 @@ min objective: +15992.031251718836 ONE_VAR_CONSTANT -+9.999999999999998 InvestmentFlowBlock_invest(storage_electricity_0) -+6.729713331080573 InvestmentFlowBlock_invest(storage_electricity_1) -+5.000276133592968 InvestmentFlowBlock_invest(storage_electricity_2) -+4.101968025099305 InvestmentFlowBlock_invest(storage_electricity_3) -+3.7152788212696146 InvestmentFlowBlock_invest(storage_electricity_4) -+3.0478226645906985 InvestmentFlowBlock_invest(storage_electricity_5) -+2.264577134183746 InvestmentFlowBlock_invest(storage_electricity_6) -+0.09137506155350818 InvestmentFlowBlock_invest(storage_electricity_7) +9.999999999999998 InvestmentFlowBlock_invest(electricity_storage_0) +6.729713331080573 InvestmentFlowBlock_invest(electricity_storage_1) +5.000276133592968 InvestmentFlowBlock_invest(electricity_storage_2) @@ -19,6 +11,14 @@ objective: +3.0478226645906985 InvestmentFlowBlock_invest(electricity_storage_5) +2.264577134183746 InvestmentFlowBlock_invest(electricity_storage_6) +0.09137506155350818 InvestmentFlowBlock_invest(electricity_storage_7) ++9.999999999999998 InvestmentFlowBlock_invest(storage_electricity_0) ++6.729713331080573 InvestmentFlowBlock_invest(storage_electricity_1) ++5.000276133592968 InvestmentFlowBlock_invest(storage_electricity_2) ++4.101968025099305 InvestmentFlowBlock_invest(storage_electricity_3) ++3.7152788212696146 InvestmentFlowBlock_invest(storage_electricity_4) ++3.0478226645906985 InvestmentFlowBlock_invest(storage_electricity_5) ++2.264577134183746 InvestmentFlowBlock_invest(storage_electricity_6) ++0.09137506155350818 InvestmentFlowBlock_invest(storage_electricity_7) +9.999999999999998 GenericInvestmentStorageBlock_invest(storage_0) +6.729713331080573 GenericInvestmentStorageBlock_invest(storage_1) +5.000276133592968 GenericInvestmentStorageBlock_invest(storage_2) @@ -652,13 +652,13 @@ objective: +0.15239954929176602 SinkDSMDIWInvestmentBlock_dsm_do_shift(demand_dsm_diw_23_23) +15.239954929176601 SinkDSMDIWInvestmentBlock_dsm_do_shed(demand_dsm_diw_23) +433.5692402297811 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_0) -+218.36744501149502 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_1) -+133.4042826150016 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_2) -+97.1465132094101 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_3) -+83.19634020751037 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_4) -+61.46421721288727 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_5) -+39.75223470007343 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_6) -+1.3782630680217502 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_7) ++291.77966959208334 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_1) ++216.7965924181011 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_2) ++177.8487160089162 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_3) ++161.08306157796636 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_4) ++132.1442157041696 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_5) ++98.1850987509782 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_6) ++3.9617416013704023 SinkDSMDIWInvestmentBlock_invest(demand_dsm_diw_7) +1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_dlr_1_0) +1 SinkDSMDLRInvestmentBlock_balance_dsm_do(demand_dsm_dlr_1_0) +1 SinkDSMDLRInvestmentBlock_dsm_up(demand_dsm_dlr_2_0) @@ -876,13 +876,13 @@ objective: +0.15239954929176602 SinkDSMDLRInvestmentBlock_balance_dsm_up(demand_dsm_dlr_2_23) +15.239954929176601 SinkDSMDLRInvestmentBlock_dsm_do_shed(demand_dsm_dlr_23) +433.5692402297811 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_0) -+218.36744501149502 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_1) -+133.4042826150016 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_2) -+97.1465132094101 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_3) -+83.19634020751037 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_4) -+61.46421721288727 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_5) -+39.75223470007343 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_6) -+1.3782630680217502 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_7) ++291.77966959208334 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_1) ++216.7965924181011 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_2) ++177.8487160089162 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_3) ++161.08306157796636 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_4) ++132.1442157041696 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_5) ++98.1850987509782 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_6) ++3.9617416013704023 SinkDSMDLRInvestmentBlock_invest(demand_dsm_dlr_7) +1 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_oemof_0) +100 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_oemof_0) +1 SinkDSMOemofInvestmentBlock_dsm_up(demand_dsm_oemof_0) @@ -956,13 +956,13 @@ objective: +0.15239954929176602 SinkDSMOemofInvestmentBlock_dsm_do_shift(demand_dsm_oemof_23) +15.239954929176601 SinkDSMOemofInvestmentBlock_dsm_do_shed(demand_dsm_oemof_23) +433.5692402297811 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_0) -+218.36744501149502 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_1) -+133.4042826150016 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_2) -+97.1465132094101 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_3) -+83.19634020751037 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_4) -+61.46421721288727 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_5) -+39.75223470007343 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_6) -+1.3782630680217502 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_7) ++291.77966959208334 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_1) ++216.7965924181011 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_2) ++177.8487160089162 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_3) ++161.08306157796636 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_4) ++132.1442157041696 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_5) ++98.1850987509782 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_6) ++3.9617416013704023 SinkDSMOemofInvestmentBlock_invest(demand_dsm_oemof_7) s.t. @@ -1158,60 +1158,6 @@ c_e_BusBlock_balance(electricity_7_23)_: -1 flow(electricity_demand_dsm_oemof_7_23) = 0 -c_e_InvestmentFlowBlock_total_rule(storage_electricity_0)_: --1 InvestmentFlowBlock_invest(storage_electricity_0) -+1 InvestmentFlowBlock_total(storage_electricity_0) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_electricity_1)_: --1 InvestmentFlowBlock_invest(storage_electricity_1) --1 InvestmentFlowBlock_total(storage_electricity_0) -+1 InvestmentFlowBlock_total(storage_electricity_1) -+1 InvestmentFlowBlock_old(storage_electricity_1) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_electricity_2)_: --1 InvestmentFlowBlock_invest(storage_electricity_2) --1 InvestmentFlowBlock_total(storage_electricity_1) -+1 InvestmentFlowBlock_total(storage_electricity_2) -+1 InvestmentFlowBlock_old(storage_electricity_2) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_electricity_3)_: --1 InvestmentFlowBlock_invest(storage_electricity_3) --1 InvestmentFlowBlock_total(storage_electricity_2) -+1 InvestmentFlowBlock_total(storage_electricity_3) -+1 InvestmentFlowBlock_old(storage_electricity_3) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_electricity_4)_: --1 InvestmentFlowBlock_invest(storage_electricity_4) --1 InvestmentFlowBlock_total(storage_electricity_3) -+1 InvestmentFlowBlock_total(storage_electricity_4) -+1 InvestmentFlowBlock_old(storage_electricity_4) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_electricity_5)_: --1 InvestmentFlowBlock_invest(storage_electricity_5) --1 InvestmentFlowBlock_total(storage_electricity_4) -+1 InvestmentFlowBlock_total(storage_electricity_5) -+1 InvestmentFlowBlock_old(storage_electricity_5) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_electricity_6)_: --1 InvestmentFlowBlock_invest(storage_electricity_6) --1 InvestmentFlowBlock_total(storage_electricity_5) -+1 InvestmentFlowBlock_total(storage_electricity_6) -+1 InvestmentFlowBlock_old(storage_electricity_6) -= 0 - -c_e_InvestmentFlowBlock_total_rule(storage_electricity_7)_: --1 InvestmentFlowBlock_invest(storage_electricity_7) --1 InvestmentFlowBlock_total(storage_electricity_6) -+1 InvestmentFlowBlock_total(storage_electricity_7) -+1 InvestmentFlowBlock_old(storage_electricity_7) -= 0 - c_e_InvestmentFlowBlock_total_rule(electricity_storage_0)_: -1 InvestmentFlowBlock_invest(electricity_storage_0) +1 InvestmentFlowBlock_total(electricity_storage_0) @@ -1266,43 +1212,58 @@ c_e_InvestmentFlowBlock_total_rule(electricity_storage_7)_: +1 InvestmentFlowBlock_old(electricity_storage_7) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_0)_: -+1 InvestmentFlowBlock_old_end(storage_electricity_0) -= 0 - -c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_1)_: +c_e_InvestmentFlowBlock_total_rule(storage_electricity_0)_: -1 InvestmentFlowBlock_invest(storage_electricity_0) -+1 InvestmentFlowBlock_old_end(storage_electricity_1) -= 0 - -c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_2)_: -+1 InvestmentFlowBlock_old_end(storage_electricity_2) ++1 InvestmentFlowBlock_total(storage_electricity_0) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_3)_: +c_e_InvestmentFlowBlock_total_rule(storage_electricity_1)_: -1 InvestmentFlowBlock_invest(storage_electricity_1) -+1 InvestmentFlowBlock_old_end(storage_electricity_3) -= 0 - -c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_4)_: -+1 InvestmentFlowBlock_old_end(storage_electricity_4) +-1 InvestmentFlowBlock_total(storage_electricity_0) ++1 InvestmentFlowBlock_total(storage_electricity_1) ++1 InvestmentFlowBlock_old(storage_electricity_1) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_5)_: +c_e_InvestmentFlowBlock_total_rule(storage_electricity_2)_: -1 InvestmentFlowBlock_invest(storage_electricity_2) -+1 InvestmentFlowBlock_old_end(storage_electricity_5) +-1 InvestmentFlowBlock_total(storage_electricity_1) ++1 InvestmentFlowBlock_total(storage_electricity_2) ++1 InvestmentFlowBlock_old(storage_electricity_2) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_6)_: +c_e_InvestmentFlowBlock_total_rule(storage_electricity_3)_: -1 InvestmentFlowBlock_invest(storage_electricity_3) +-1 InvestmentFlowBlock_total(storage_electricity_2) ++1 InvestmentFlowBlock_total(storage_electricity_3) ++1 InvestmentFlowBlock_old(storage_electricity_3) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_electricity_4)_: -1 InvestmentFlowBlock_invest(storage_electricity_4) -+1 InvestmentFlowBlock_old_end(storage_electricity_6) +-1 InvestmentFlowBlock_total(storage_electricity_3) ++1 InvestmentFlowBlock_total(storage_electricity_4) ++1 InvestmentFlowBlock_old(storage_electricity_4) = 0 -c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_7)_: +c_e_InvestmentFlowBlock_total_rule(storage_electricity_5)_: -1 InvestmentFlowBlock_invest(storage_electricity_5) +-1 InvestmentFlowBlock_total(storage_electricity_4) ++1 InvestmentFlowBlock_total(storage_electricity_5) ++1 InvestmentFlowBlock_old(storage_electricity_5) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_electricity_6)_: -1 InvestmentFlowBlock_invest(storage_electricity_6) -+1 InvestmentFlowBlock_old_end(storage_electricity_7) +-1 InvestmentFlowBlock_total(storage_electricity_5) ++1 InvestmentFlowBlock_total(storage_electricity_6) ++1 InvestmentFlowBlock_old(storage_electricity_6) += 0 + +c_e_InvestmentFlowBlock_total_rule(storage_electricity_7)_: +-1 InvestmentFlowBlock_invest(storage_electricity_7) +-1 InvestmentFlowBlock_total(storage_electricity_6) ++1 InvestmentFlowBlock_total(storage_electricity_7) ++1 InvestmentFlowBlock_old(storage_electricity_7) = 0 c_e_InvestmentFlowBlock_old_rule_end(electricity_storage_0)_: @@ -1344,36 +1305,43 @@ c_e_InvestmentFlowBlock_old_rule_end(electricity_storage_7)_: +1 InvestmentFlowBlock_old_end(electricity_storage_7) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_0)_: -+1 InvestmentFlowBlock_old_exo(storage_electricity_0) +c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_0)_: ++1 InvestmentFlowBlock_old_end(storage_electricity_0) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_1)_: -+1 InvestmentFlowBlock_old_exo(storage_electricity_1) +c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_1)_: +-1 InvestmentFlowBlock_invest(storage_electricity_0) ++1 InvestmentFlowBlock_old_end(storage_electricity_1) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_2)_: -+1 InvestmentFlowBlock_old_exo(storage_electricity_2) +c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_2)_: ++1 InvestmentFlowBlock_old_end(storage_electricity_2) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_3)_: -+1 InvestmentFlowBlock_old_exo(storage_electricity_3) +c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_3)_: +-1 InvestmentFlowBlock_invest(storage_electricity_1) ++1 InvestmentFlowBlock_old_end(storage_electricity_3) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_4)_: -+1 InvestmentFlowBlock_old_exo(storage_electricity_4) +c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_4)_: ++1 InvestmentFlowBlock_old_end(storage_electricity_4) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_5)_: -+1 InvestmentFlowBlock_old_exo(storage_electricity_5) +c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_5)_: +-1 InvestmentFlowBlock_invest(storage_electricity_2) ++1 InvestmentFlowBlock_old_end(storage_electricity_5) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_6)_: -+1 InvestmentFlowBlock_old_exo(storage_electricity_6) +c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_6)_: +-1 InvestmentFlowBlock_invest(storage_electricity_3) +-1 InvestmentFlowBlock_invest(storage_electricity_4) ++1 InvestmentFlowBlock_old_end(storage_electricity_6) = 0 -c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_7)_: -+1 InvestmentFlowBlock_old_exo(storage_electricity_7) +c_e_InvestmentFlowBlock_old_rule_end(storage_electricity_7)_: +-1 InvestmentFlowBlock_invest(storage_electricity_5) +-1 InvestmentFlowBlock_invest(storage_electricity_6) ++1 InvestmentFlowBlock_old_end(storage_electricity_7) = 0 c_e_InvestmentFlowBlock_old_rule_exo(electricity_storage_0)_: @@ -1408,52 +1376,36 @@ c_e_InvestmentFlowBlock_old_rule_exo(electricity_storage_7)_: +1 InvestmentFlowBlock_old_exo(electricity_storage_7) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_electricity_0)_: --1 InvestmentFlowBlock_old_end(storage_electricity_0) --1 InvestmentFlowBlock_old_exo(storage_electricity_0) -+1 InvestmentFlowBlock_old(storage_electricity_0) +c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_0)_: ++1 InvestmentFlowBlock_old_exo(storage_electricity_0) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_electricity_1)_: -+1 InvestmentFlowBlock_old(storage_electricity_1) --1 InvestmentFlowBlock_old_end(storage_electricity_1) --1 InvestmentFlowBlock_old_exo(storage_electricity_1) +c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_1)_: ++1 InvestmentFlowBlock_old_exo(storage_electricity_1) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_electricity_2)_: -+1 InvestmentFlowBlock_old(storage_electricity_2) --1 InvestmentFlowBlock_old_end(storage_electricity_2) --1 InvestmentFlowBlock_old_exo(storage_electricity_2) +c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_2)_: ++1 InvestmentFlowBlock_old_exo(storage_electricity_2) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_electricity_3)_: -+1 InvestmentFlowBlock_old(storage_electricity_3) --1 InvestmentFlowBlock_old_end(storage_electricity_3) --1 InvestmentFlowBlock_old_exo(storage_electricity_3) +c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_3)_: ++1 InvestmentFlowBlock_old_exo(storage_electricity_3) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_electricity_4)_: -+1 InvestmentFlowBlock_old(storage_electricity_4) --1 InvestmentFlowBlock_old_end(storage_electricity_4) --1 InvestmentFlowBlock_old_exo(storage_electricity_4) +c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_4)_: ++1 InvestmentFlowBlock_old_exo(storage_electricity_4) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_electricity_5)_: -+1 InvestmentFlowBlock_old(storage_electricity_5) --1 InvestmentFlowBlock_old_end(storage_electricity_5) --1 InvestmentFlowBlock_old_exo(storage_electricity_5) +c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_5)_: ++1 InvestmentFlowBlock_old_exo(storage_electricity_5) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_electricity_6)_: -+1 InvestmentFlowBlock_old(storage_electricity_6) --1 InvestmentFlowBlock_old_end(storage_electricity_6) --1 InvestmentFlowBlock_old_exo(storage_electricity_6) +c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_6)_: ++1 InvestmentFlowBlock_old_exo(storage_electricity_6) = 0 -c_e_InvestmentFlowBlock_old_rule(storage_electricity_7)_: -+1 InvestmentFlowBlock_old(storage_electricity_7) --1 InvestmentFlowBlock_old_end(storage_electricity_7) --1 InvestmentFlowBlock_old_exo(storage_electricity_7) +c_e_InvestmentFlowBlock_old_rule_exo(storage_electricity_7)_: ++1 InvestmentFlowBlock_old_exo(storage_electricity_7) = 0 c_e_InvestmentFlowBlock_old_rule(electricity_storage_0)_: @@ -1504,125 +1456,53 @@ c_e_InvestmentFlowBlock_old_rule(electricity_storage_7)_: -1 InvestmentFlowBlock_old_exo(electricity_storage_7) = 0 -c_u_InvestmentFlowBlock_max(storage_electricity_0_0)_: -+1 flow(storage_electricity_0_0) --1 InvestmentFlowBlock_total(storage_electricity_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_0_1)_: -+1 flow(storage_electricity_0_1) --1 InvestmentFlowBlock_total(storage_electricity_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_0_2)_: -+1 flow(storage_electricity_0_2) --1 InvestmentFlowBlock_total(storage_electricity_0) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_1_3)_: -+1 flow(storage_electricity_1_3) --1 InvestmentFlowBlock_total(storage_electricity_1) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_1_4)_: -+1 flow(storage_electricity_1_4) --1 InvestmentFlowBlock_total(storage_electricity_1) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_1_5)_: -+1 flow(storage_electricity_1_5) --1 InvestmentFlowBlock_total(storage_electricity_1) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_2_6)_: -+1 flow(storage_electricity_2_6) --1 InvestmentFlowBlock_total(storage_electricity_2) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_2_7)_: -+1 flow(storage_electricity_2_7) --1 InvestmentFlowBlock_total(storage_electricity_2) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_2_8)_: -+1 flow(storage_electricity_2_8) --1 InvestmentFlowBlock_total(storage_electricity_2) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_3_9)_: -+1 flow(storage_electricity_3_9) --1 InvestmentFlowBlock_total(storage_electricity_3) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_3_10)_: -+1 flow(storage_electricity_3_10) --1 InvestmentFlowBlock_total(storage_electricity_3) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_3_11)_: -+1 flow(storage_electricity_3_11) --1 InvestmentFlowBlock_total(storage_electricity_3) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_4_12)_: -+1 flow(storage_electricity_4_12) --1 InvestmentFlowBlock_total(storage_electricity_4) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_4_13)_: -+1 flow(storage_electricity_4_13) --1 InvestmentFlowBlock_total(storage_electricity_4) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_4_14)_: -+1 flow(storage_electricity_4_14) --1 InvestmentFlowBlock_total(storage_electricity_4) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_5_15)_: -+1 flow(storage_electricity_5_15) --1 InvestmentFlowBlock_total(storage_electricity_5) -<= 0 - -c_u_InvestmentFlowBlock_max(storage_electricity_5_16)_: -+1 flow(storage_electricity_5_16) --1 InvestmentFlowBlock_total(storage_electricity_5) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_electricity_0)_: +-1 InvestmentFlowBlock_old_end(storage_electricity_0) +-1 InvestmentFlowBlock_old_exo(storage_electricity_0) ++1 InvestmentFlowBlock_old(storage_electricity_0) += 0 -c_u_InvestmentFlowBlock_max(storage_electricity_5_17)_: -+1 flow(storage_electricity_5_17) --1 InvestmentFlowBlock_total(storage_electricity_5) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_electricity_1)_: ++1 InvestmentFlowBlock_old(storage_electricity_1) +-1 InvestmentFlowBlock_old_end(storage_electricity_1) +-1 InvestmentFlowBlock_old_exo(storage_electricity_1) += 0 -c_u_InvestmentFlowBlock_max(storage_electricity_6_18)_: -+1 flow(storage_electricity_6_18) --1 InvestmentFlowBlock_total(storage_electricity_6) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_electricity_2)_: ++1 InvestmentFlowBlock_old(storage_electricity_2) +-1 InvestmentFlowBlock_old_end(storage_electricity_2) +-1 InvestmentFlowBlock_old_exo(storage_electricity_2) += 0 -c_u_InvestmentFlowBlock_max(storage_electricity_6_19)_: -+1 flow(storage_electricity_6_19) --1 InvestmentFlowBlock_total(storage_electricity_6) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_electricity_3)_: ++1 InvestmentFlowBlock_old(storage_electricity_3) +-1 InvestmentFlowBlock_old_end(storage_electricity_3) +-1 InvestmentFlowBlock_old_exo(storage_electricity_3) += 0 -c_u_InvestmentFlowBlock_max(storage_electricity_6_20)_: -+1 flow(storage_electricity_6_20) --1 InvestmentFlowBlock_total(storage_electricity_6) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_electricity_4)_: ++1 InvestmentFlowBlock_old(storage_electricity_4) +-1 InvestmentFlowBlock_old_end(storage_electricity_4) +-1 InvestmentFlowBlock_old_exo(storage_electricity_4) += 0 -c_u_InvestmentFlowBlock_max(storage_electricity_7_21)_: -+1 flow(storage_electricity_7_21) --1 InvestmentFlowBlock_total(storage_electricity_7) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_electricity_5)_: ++1 InvestmentFlowBlock_old(storage_electricity_5) +-1 InvestmentFlowBlock_old_end(storage_electricity_5) +-1 InvestmentFlowBlock_old_exo(storage_electricity_5) += 0 -c_u_InvestmentFlowBlock_max(storage_electricity_7_22)_: -+1 flow(storage_electricity_7_22) --1 InvestmentFlowBlock_total(storage_electricity_7) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_electricity_6)_: ++1 InvestmentFlowBlock_old(storage_electricity_6) +-1 InvestmentFlowBlock_old_end(storage_electricity_6) +-1 InvestmentFlowBlock_old_exo(storage_electricity_6) += 0 -c_u_InvestmentFlowBlock_max(storage_electricity_7_23)_: -+1 flow(storage_electricity_7_23) --1 InvestmentFlowBlock_total(storage_electricity_7) -<= 0 +c_e_InvestmentFlowBlock_old_rule(storage_electricity_7)_: ++1 InvestmentFlowBlock_old(storage_electricity_7) +-1 InvestmentFlowBlock_old_end(storage_electricity_7) +-1 InvestmentFlowBlock_old_exo(storage_electricity_7) += 0 c_u_InvestmentFlowBlock_max(electricity_storage_0_0)_: +1 flow(electricity_storage_0_0) @@ -1744,6 +1624,126 @@ c_u_InvestmentFlowBlock_max(electricity_storage_7_23)_: -1 InvestmentFlowBlock_total(electricity_storage_7) <= 0 +c_u_InvestmentFlowBlock_max(storage_electricity_0_0)_: ++1 flow(storage_electricity_0_0) +-1 InvestmentFlowBlock_total(storage_electricity_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_0_1)_: ++1 flow(storage_electricity_0_1) +-1 InvestmentFlowBlock_total(storage_electricity_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_0_2)_: ++1 flow(storage_electricity_0_2) +-1 InvestmentFlowBlock_total(storage_electricity_0) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_1_3)_: ++1 flow(storage_electricity_1_3) +-1 InvestmentFlowBlock_total(storage_electricity_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_1_4)_: ++1 flow(storage_electricity_1_4) +-1 InvestmentFlowBlock_total(storage_electricity_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_1_5)_: ++1 flow(storage_electricity_1_5) +-1 InvestmentFlowBlock_total(storage_electricity_1) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_2_6)_: ++1 flow(storage_electricity_2_6) +-1 InvestmentFlowBlock_total(storage_electricity_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_2_7)_: ++1 flow(storage_electricity_2_7) +-1 InvestmentFlowBlock_total(storage_electricity_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_2_8)_: ++1 flow(storage_electricity_2_8) +-1 InvestmentFlowBlock_total(storage_electricity_2) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_3_9)_: ++1 flow(storage_electricity_3_9) +-1 InvestmentFlowBlock_total(storage_electricity_3) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_3_10)_: ++1 flow(storage_electricity_3_10) +-1 InvestmentFlowBlock_total(storage_electricity_3) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_3_11)_: ++1 flow(storage_electricity_3_11) +-1 InvestmentFlowBlock_total(storage_electricity_3) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_4_12)_: ++1 flow(storage_electricity_4_12) +-1 InvestmentFlowBlock_total(storage_electricity_4) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_4_13)_: ++1 flow(storage_electricity_4_13) +-1 InvestmentFlowBlock_total(storage_electricity_4) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_4_14)_: ++1 flow(storage_electricity_4_14) +-1 InvestmentFlowBlock_total(storage_electricity_4) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_5_15)_: ++1 flow(storage_electricity_5_15) +-1 InvestmentFlowBlock_total(storage_electricity_5) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_5_16)_: ++1 flow(storage_electricity_5_16) +-1 InvestmentFlowBlock_total(storage_electricity_5) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_5_17)_: ++1 flow(storage_electricity_5_17) +-1 InvestmentFlowBlock_total(storage_electricity_5) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_6_18)_: ++1 flow(storage_electricity_6_18) +-1 InvestmentFlowBlock_total(storage_electricity_6) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_6_19)_: ++1 flow(storage_electricity_6_19) +-1 InvestmentFlowBlock_total(storage_electricity_6) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_6_20)_: ++1 flow(storage_electricity_6_20) +-1 InvestmentFlowBlock_total(storage_electricity_6) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_7_21)_: ++1 flow(storage_electricity_7_21) +-1 InvestmentFlowBlock_total(storage_electricity_7) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_7_22)_: ++1 flow(storage_electricity_7_22) +-1 InvestmentFlowBlock_total(storage_electricity_7) +<= 0 + +c_u_InvestmentFlowBlock_max(storage_electricity_7_23)_: ++1 flow(storage_electricity_7_23) +-1 InvestmentFlowBlock_total(storage_electricity_7) +<= 0 + c_e_GenericInvestmentStorageBlock_total_storage_rule(storage_0)_: -1 GenericInvestmentStorageBlock_invest(storage_0) +1 GenericInvestmentStorageBlock_total(storage_0) @@ -2083,43 +2083,43 @@ c_e_GenericInvestmentStorageBlock_balance(storage_7_23)_: = 0 c_e_GenericInvestmentStorageBlock_power_coupled(storage_0)_: -+1 InvestmentFlowBlock_total(storage_electricity_0) -1 InvestmentFlowBlock_total(electricity_storage_0) ++1 InvestmentFlowBlock_total(storage_electricity_0) = 0 c_e_GenericInvestmentStorageBlock_power_coupled(storage_1)_: -+1 InvestmentFlowBlock_total(storage_electricity_1) -1 InvestmentFlowBlock_total(electricity_storage_1) ++1 InvestmentFlowBlock_total(storage_electricity_1) = 0 c_e_GenericInvestmentStorageBlock_power_coupled(storage_2)_: -+1 InvestmentFlowBlock_total(storage_electricity_2) -1 InvestmentFlowBlock_total(electricity_storage_2) ++1 InvestmentFlowBlock_total(storage_electricity_2) = 0 c_e_GenericInvestmentStorageBlock_power_coupled(storage_3)_: -+1 InvestmentFlowBlock_total(storage_electricity_3) -1 InvestmentFlowBlock_total(electricity_storage_3) ++1 InvestmentFlowBlock_total(storage_electricity_3) = 0 c_e_GenericInvestmentStorageBlock_power_coupled(storage_4)_: -+1 InvestmentFlowBlock_total(storage_electricity_4) -1 InvestmentFlowBlock_total(electricity_storage_4) ++1 InvestmentFlowBlock_total(storage_electricity_4) = 0 c_e_GenericInvestmentStorageBlock_power_coupled(storage_5)_: -+1 InvestmentFlowBlock_total(storage_electricity_5) -1 InvestmentFlowBlock_total(electricity_storage_5) ++1 InvestmentFlowBlock_total(storage_electricity_5) = 0 c_e_GenericInvestmentStorageBlock_power_coupled(storage_6)_: -+1 InvestmentFlowBlock_total(storage_electricity_6) -1 InvestmentFlowBlock_total(electricity_storage_6) ++1 InvestmentFlowBlock_total(storage_electricity_6) = 0 c_e_GenericInvestmentStorageBlock_power_coupled(storage_7)_: -+1 InvestmentFlowBlock_total(storage_electricity_7) -1 InvestmentFlowBlock_total(electricity_storage_7) ++1 InvestmentFlowBlock_total(storage_electricity_7) = 0 c_e_GenericInvestmentStorageBlock_storage_capacity_outflow(storage_0)_: @@ -6718,14 +6718,6 @@ c_l_SinkDSMOemofInvestmentBlock_overall_minimum(demand_dsm_oemof)_: bounds 1 <= ONE_VAR_CONSTANT <= 1 - 0 <= InvestmentFlowBlock_invest(storage_electricity_0) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_electricity_1) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_electricity_2) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_electricity_3) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_electricity_4) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_electricity_5) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_electricity_6) <= +inf - 0 <= InvestmentFlowBlock_invest(storage_electricity_7) <= +inf 0 <= InvestmentFlowBlock_invest(electricity_storage_0) <= +inf 0 <= InvestmentFlowBlock_invest(electricity_storage_1) <= +inf 0 <= InvestmentFlowBlock_invest(electricity_storage_2) <= +inf @@ -6734,6 +6726,14 @@ bounds 0 <= InvestmentFlowBlock_invest(electricity_storage_5) <= +inf 0 <= InvestmentFlowBlock_invest(electricity_storage_6) <= +inf 0 <= InvestmentFlowBlock_invest(electricity_storage_7) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_electricity_0) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_electricity_3) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_electricity_4) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_electricity_5) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_electricity_6) <= +inf + 0 <= InvestmentFlowBlock_invest(storage_electricity_7) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage_0) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage_1) <= +inf 0 <= GenericInvestmentStorageBlock_invest(storage_2) <= +inf @@ -7798,21 +7798,6 @@ bounds 0 <= flow(electricity_demand_dsm_diw_7_23) <= +inf 0 <= flow(electricity_demand_dsm_dlr_7_23) <= +inf 0 <= flow(electricity_demand_dsm_oemof_7_23) <= +inf - 0 <= InvestmentFlowBlock_total(storage_electricity_0) <= +inf - 0 <= InvestmentFlowBlock_total(storage_electricity_1) <= +inf - 0 <= InvestmentFlowBlock_old(storage_electricity_1) <= +inf - 0 <= InvestmentFlowBlock_total(storage_electricity_2) <= +inf - 0 <= InvestmentFlowBlock_old(storage_electricity_2) <= +inf - 0 <= InvestmentFlowBlock_total(storage_electricity_3) <= +inf - 0 <= InvestmentFlowBlock_old(storage_electricity_3) <= +inf - 0 <= InvestmentFlowBlock_total(storage_electricity_4) <= +inf - 0 <= InvestmentFlowBlock_old(storage_electricity_4) <= +inf - 0 <= InvestmentFlowBlock_total(storage_electricity_5) <= +inf - 0 <= InvestmentFlowBlock_old(storage_electricity_5) <= +inf - 0 <= InvestmentFlowBlock_total(storage_electricity_6) <= +inf - 0 <= InvestmentFlowBlock_old(storage_electricity_6) <= +inf - 0 <= InvestmentFlowBlock_total(storage_electricity_7) <= +inf - 0 <= InvestmentFlowBlock_old(storage_electricity_7) <= +inf 0 <= InvestmentFlowBlock_total(electricity_storage_0) <= +inf 0 <= InvestmentFlowBlock_total(electricity_storage_1) <= +inf 0 <= InvestmentFlowBlock_old(electricity_storage_1) <= +inf @@ -7828,14 +7813,21 @@ bounds 0 <= InvestmentFlowBlock_old(electricity_storage_6) <= +inf 0 <= InvestmentFlowBlock_total(electricity_storage_7) <= +inf 0 <= InvestmentFlowBlock_old(electricity_storage_7) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_electricity_0) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_electricity_1) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_electricity_2) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_electricity_3) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_electricity_4) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_electricity_5) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_electricity_6) <= +inf - 0 <= InvestmentFlowBlock_old_end(storage_electricity_7) <= +inf + 0 <= InvestmentFlowBlock_total(storage_electricity_0) <= +inf + 0 <= InvestmentFlowBlock_total(storage_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_old(storage_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_total(storage_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_old(storage_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_total(storage_electricity_3) <= +inf + 0 <= InvestmentFlowBlock_old(storage_electricity_3) <= +inf + 0 <= InvestmentFlowBlock_total(storage_electricity_4) <= +inf + 0 <= InvestmentFlowBlock_old(storage_electricity_4) <= +inf + 0 <= InvestmentFlowBlock_total(storage_electricity_5) <= +inf + 0 <= InvestmentFlowBlock_old(storage_electricity_5) <= +inf + 0 <= InvestmentFlowBlock_total(storage_electricity_6) <= +inf + 0 <= InvestmentFlowBlock_old(storage_electricity_6) <= +inf + 0 <= InvestmentFlowBlock_total(storage_electricity_7) <= +inf + 0 <= InvestmentFlowBlock_old(storage_electricity_7) <= +inf 0 <= InvestmentFlowBlock_old_end(electricity_storage_0) <= +inf 0 <= InvestmentFlowBlock_old_end(electricity_storage_1) <= +inf 0 <= InvestmentFlowBlock_old_end(electricity_storage_2) <= +inf @@ -7844,14 +7836,14 @@ bounds 0 <= InvestmentFlowBlock_old_end(electricity_storage_5) <= +inf 0 <= InvestmentFlowBlock_old_end(electricity_storage_6) <= +inf 0 <= InvestmentFlowBlock_old_end(electricity_storage_7) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_electricity_0) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_electricity_1) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_electricity_2) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_electricity_3) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_electricity_4) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_electricity_5) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_electricity_6) <= +inf - 0 <= InvestmentFlowBlock_old_exo(storage_electricity_7) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_electricity_0) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_electricity_3) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_electricity_4) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_electricity_5) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_electricity_6) <= +inf + 0 <= InvestmentFlowBlock_old_end(storage_electricity_7) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricity_storage_0) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricity_storage_1) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricity_storage_2) <= +inf @@ -7860,8 +7852,16 @@ bounds 0 <= InvestmentFlowBlock_old_exo(electricity_storage_5) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricity_storage_6) <= +inf 0 <= InvestmentFlowBlock_old_exo(electricity_storage_7) <= +inf - 0 <= InvestmentFlowBlock_old(storage_electricity_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_electricity_0) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_electricity_1) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_electricity_2) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_electricity_3) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_electricity_4) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_electricity_5) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_electricity_6) <= +inf + 0 <= InvestmentFlowBlock_old_exo(storage_electricity_7) <= +inf 0 <= InvestmentFlowBlock_old(electricity_storage_0) <= +inf + 0 <= InvestmentFlowBlock_old(storage_electricity_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_0) <= +inf 0 <= GenericInvestmentStorageBlock_total(storage_1) <= +inf 0 <= GenericInvestmentStorageBlock_old(storage_1) <= +inf diff --git a/tests/lp_files/storage_invest_multi_period.lp b/tests/lp_files/storage_invest_multi_period.lp index 49c4f5e84..e8b1246e4 100644 --- a/tests/lp_files/storage_invest_multi_period.lp +++ b/tests/lp_files/storage_invest_multi_period.lp @@ -3,9 +3,9 @@ min objective: +250.0 ONE_VAR_CONSTANT -+29.99406858132935 GenericInvestmentStorageBlock_invest(storage1_0) -+19.60706904757886 GenericInvestmentStorageBlock_invest(storage1_1) -+9.614085282931445 GenericInvestmentStorageBlock_invest(storage1_2) ++29.994068581329355 GenericInvestmentStorageBlock_invest(storage1_0) ++19.797418159157367 GenericInvestmentStorageBlock_invest(storage1_1) ++9.8007020589888 GenericInvestmentStorageBlock_invest(storage1_2) s.t. From bbc34ac3f53fcf9c4aaa7e925c86c1256cf069d7 Mon Sep 17 00:00:00 2001 From: "Julian.Endres" Date: Tue, 5 Dec 2023 17:24:30 +0100 Subject: [PATCH 136/180] Add fixed costs to multi-period converter tests Fixed costs were not included in the converter test and thus changes in fixed costs discounting not tested before. --- .../lp_files/converter_invest_multi_period.lp | 142 +++++++++--------- tests/multi_period_constraint_tests.py | 1 + 2 files changed, 72 insertions(+), 71 deletions(-) diff --git a/tests/lp_files/converter_invest_multi_period.lp b/tests/lp_files/converter_invest_multi_period.lp index 1ac09ba27..35ada8c5b 100644 --- a/tests/lp_files/converter_invest_multi_period.lp +++ b/tests/lp_files/converter_invest_multi_period.lp @@ -2,9 +2,9 @@ min objective: -+3.5273767282312036 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) -+2.328225392441188 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_1) -+1.1525868279411837 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_2) ++32.94298610923851 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) ++21.74383477344849 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_1) ++10.764274640321037 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_2) +50 flow(powerplant_gas_coal_electricityBus_0_0) +50 flow(powerplant_gas_coal_electricityBus_0_1) +49.01960784313725 flow(powerplant_gas_coal_electricityBus_1_2) @@ -44,28 +44,28 @@ c_e_BusBlock_balance(electricityBus_2_5)_: +1 flow(powerplant_gas_coal_electricityBus_2_5) = 0 -c_e_BusBlock_balance(gasBus_0_0)_: -+1 flow(gasBus_powerplant_gas_coal_0_0) +c_e_BusBlock_balance(coalBus_0_0)_: ++1 flow(coalBus_powerplant_gas_coal_0_0) = 0 -c_e_BusBlock_balance(gasBus_0_1)_: -+1 flow(gasBus_powerplant_gas_coal_0_1) +c_e_BusBlock_balance(coalBus_0_1)_: ++1 flow(coalBus_powerplant_gas_coal_0_1) = 0 -c_e_BusBlock_balance(gasBus_1_2)_: -+1 flow(gasBus_powerplant_gas_coal_1_2) +c_e_BusBlock_balance(coalBus_1_2)_: ++1 flow(coalBus_powerplant_gas_coal_1_2) = 0 -c_e_BusBlock_balance(gasBus_1_3)_: -+1 flow(gasBus_powerplant_gas_coal_1_3) +c_e_BusBlock_balance(coalBus_1_3)_: ++1 flow(coalBus_powerplant_gas_coal_1_3) = 0 -c_e_BusBlock_balance(gasBus_2_4)_: -+1 flow(gasBus_powerplant_gas_coal_2_4) +c_e_BusBlock_balance(coalBus_2_4)_: ++1 flow(coalBus_powerplant_gas_coal_2_4) = 0 -c_e_BusBlock_balance(gasBus_2_5)_: -+1 flow(gasBus_powerplant_gas_coal_2_5) +c_e_BusBlock_balance(coalBus_2_5)_: ++1 flow(coalBus_powerplant_gas_coal_2_5) = 0 c_e_BusBlock_balance(thermalBus_0_0)_: @@ -92,33 +92,28 @@ c_e_BusBlock_balance(thermalBus_2_5)_: +1 flow(powerplant_gas_coal_thermalBus_2_5) = 0 -c_e_BusBlock_balance(coalBus_0_0)_: -+1 flow(coalBus_powerplant_gas_coal_0_0) -= 0 - -c_e_BusBlock_balance(coalBus_0_1)_: -+1 flow(coalBus_powerplant_gas_coal_0_1) +c_e_BusBlock_balance(gasBus_0_0)_: ++1 flow(gasBus_powerplant_gas_coal_0_0) = 0 -c_e_BusBlock_balance(coalBus_1_2)_: -+1 flow(coalBus_powerplant_gas_coal_1_2) +c_e_BusBlock_balance(gasBus_0_1)_: ++1 flow(gasBus_powerplant_gas_coal_0_1) = 0 -c_e_BusBlock_balance(coalBus_1_3)_: -+1 flow(coalBus_powerplant_gas_coal_1_3) +c_e_BusBlock_balance(gasBus_1_2)_: ++1 flow(gasBus_powerplant_gas_coal_1_2) = 0 -c_e_BusBlock_balance(coalBus_2_4)_: -+1 flow(coalBus_powerplant_gas_coal_2_4) +c_e_BusBlock_balance(gasBus_1_3)_: ++1 flow(gasBus_powerplant_gas_coal_1_3) = 0 -c_e_BusBlock_balance(coalBus_2_5)_: -+1 flow(coalBus_powerplant_gas_coal_2_5) +c_e_BusBlock_balance(gasBus_2_4)_: ++1 flow(gasBus_powerplant_gas_coal_2_4) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_0)_: --0.58 flow(powerplant_gas_coal_electricityBus_0_0) -+0.3 flow(gasBus_powerplant_gas_coal_0_0) +c_e_BusBlock_balance(gasBus_2_5)_: ++1 flow(gasBus_powerplant_gas_coal_2_5) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_0)_: @@ -126,9 +121,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_0)_: +0.3 flow(coalBus_powerplant_gas_coal_0_0) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_0)_: --0.58 flow(powerplant_gas_coal_thermalBus_0_0) -+0.5 flow(gasBus_powerplant_gas_coal_0_0) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_0)_: +-0.58 flow(powerplant_gas_coal_electricityBus_0_0) ++0.3 flow(gasBus_powerplant_gas_coal_0_0) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_0)_: @@ -136,9 +131,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_0)_: +0.5 flow(coalBus_powerplant_gas_coal_0_0) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_1)_: --0.58 flow(powerplant_gas_coal_electricityBus_0_1) -+0.3 flow(gasBus_powerplant_gas_coal_0_1) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_0)_: +-0.58 flow(powerplant_gas_coal_thermalBus_0_0) ++0.5 flow(gasBus_powerplant_gas_coal_0_0) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_1)_: @@ -146,9 +141,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_0_1)_: +0.3 flow(coalBus_powerplant_gas_coal_0_1) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_1)_: --0.58 flow(powerplant_gas_coal_thermalBus_0_1) -+0.5 flow(gasBus_powerplant_gas_coal_0_1) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_0_1)_: +-0.58 flow(powerplant_gas_coal_electricityBus_0_1) ++0.3 flow(gasBus_powerplant_gas_coal_0_1) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_1)_: @@ -156,9 +151,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_0_1)_: +0.5 flow(coalBus_powerplant_gas_coal_0_1) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_2)_: --0.58 flow(powerplant_gas_coal_electricityBus_1_2) -+0.3 flow(gasBus_powerplant_gas_coal_1_2) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_0_1)_: +-0.58 flow(powerplant_gas_coal_thermalBus_0_1) ++0.5 flow(gasBus_powerplant_gas_coal_0_1) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_2)_: @@ -166,9 +161,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_2)_: +0.3 flow(coalBus_powerplant_gas_coal_1_2) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_2)_: --0.58 flow(powerplant_gas_coal_thermalBus_1_2) -+0.5 flow(gasBus_powerplant_gas_coal_1_2) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_2)_: +-0.58 flow(powerplant_gas_coal_electricityBus_1_2) ++0.3 flow(gasBus_powerplant_gas_coal_1_2) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_2)_: @@ -176,9 +171,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_2)_: +0.5 flow(coalBus_powerplant_gas_coal_1_2) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_3)_: --0.58 flow(powerplant_gas_coal_electricityBus_1_3) -+0.3 flow(gasBus_powerplant_gas_coal_1_3) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_2)_: +-0.58 flow(powerplant_gas_coal_thermalBus_1_2) ++0.5 flow(gasBus_powerplant_gas_coal_1_2) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_3)_: @@ -186,9 +181,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_1_3)_: +0.3 flow(coalBus_powerplant_gas_coal_1_3) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_3)_: --0.58 flow(powerplant_gas_coal_thermalBus_1_3) -+0.5 flow(gasBus_powerplant_gas_coal_1_3) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_1_3)_: +-0.58 flow(powerplant_gas_coal_electricityBus_1_3) ++0.3 flow(gasBus_powerplant_gas_coal_1_3) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_3)_: @@ -196,9 +191,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_1_3)_: +0.5 flow(coalBus_powerplant_gas_coal_1_3) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_4)_: --0.58 flow(powerplant_gas_coal_electricityBus_2_4) -+0.3 flow(gasBus_powerplant_gas_coal_2_4) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_1_3)_: +-0.58 flow(powerplant_gas_coal_thermalBus_1_3) ++0.5 flow(gasBus_powerplant_gas_coal_1_3) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_4)_: @@ -206,9 +201,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_4)_: +0.3 flow(coalBus_powerplant_gas_coal_2_4) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_4)_: --0.58 flow(powerplant_gas_coal_thermalBus_2_4) -+0.5 flow(gasBus_powerplant_gas_coal_2_4) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_4)_: +-0.58 flow(powerplant_gas_coal_electricityBus_2_4) ++0.3 flow(gasBus_powerplant_gas_coal_2_4) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_4)_: @@ -216,9 +211,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_4)_: +0.5 flow(coalBus_powerplant_gas_coal_2_4) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_5)_: --0.58 flow(powerplant_gas_coal_electricityBus_2_5) -+0.3 flow(gasBus_powerplant_gas_coal_2_5) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_4)_: +-0.58 flow(powerplant_gas_coal_thermalBus_2_4) ++0.5 flow(gasBus_powerplant_gas_coal_2_4) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_5)_: @@ -226,9 +221,9 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_electricityBus_2_5)_: +0.3 flow(coalBus_powerplant_gas_coal_2_5) = 0 -c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_5)_: --0.58 flow(powerplant_gas_coal_thermalBus_2_5) -+0.5 flow(gasBus_powerplant_gas_coal_2_5) +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_electricityBus_2_5)_: +-0.58 flow(powerplant_gas_coal_electricityBus_2_5) ++0.3 flow(gasBus_powerplant_gas_coal_2_5) = 0 c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_5)_: @@ -236,6 +231,11 @@ c_e_ConverterBlock_relation(powerplant_gas_coal_coalBus_thermalBus_2_5)_: +0.5 flow(coalBus_powerplant_gas_coal_2_5) = 0 +c_e_ConverterBlock_relation(powerplant_gas_coal_gasBus_thermalBus_2_5)_: +-0.58 flow(powerplant_gas_coal_thermalBus_2_5) ++0.5 flow(gasBus_powerplant_gas_coal_2_5) += 0 + c_e_InvestmentFlowBlock_total_rule(powerplant_gas_coal_electricityBus_0)_: -1 InvestmentFlowBlock_invest(powerplant_gas_coal_electricityBus_0) +1 InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_0) @@ -343,18 +343,18 @@ bounds 0 <= flow(powerplant_gas_coal_thermalBus_1_3) <= +inf 0 <= flow(powerplant_gas_coal_thermalBus_2_4) <= +inf 0 <= flow(powerplant_gas_coal_thermalBus_2_5) <= +inf - 0 <= flow(gasBus_powerplant_gas_coal_0_0) <= +inf - 0 <= flow(gasBus_powerplant_gas_coal_0_1) <= +inf - 0 <= flow(gasBus_powerplant_gas_coal_1_2) <= +inf - 0 <= flow(gasBus_powerplant_gas_coal_1_3) <= +inf - 0 <= flow(gasBus_powerplant_gas_coal_2_4) <= +inf - 0 <= flow(gasBus_powerplant_gas_coal_2_5) <= +inf 0 <= flow(coalBus_powerplant_gas_coal_0_0) <= +inf 0 <= flow(coalBus_powerplant_gas_coal_0_1) <= +inf 0 <= flow(coalBus_powerplant_gas_coal_1_2) <= +inf 0 <= flow(coalBus_powerplant_gas_coal_1_3) <= +inf 0 <= flow(coalBus_powerplant_gas_coal_2_4) <= +inf 0 <= flow(coalBus_powerplant_gas_coal_2_5) <= +inf + 0 <= flow(gasBus_powerplant_gas_coal_0_0) <= +inf + 0 <= flow(gasBus_powerplant_gas_coal_0_1) <= +inf + 0 <= flow(gasBus_powerplant_gas_coal_1_2) <= +inf + 0 <= flow(gasBus_powerplant_gas_coal_1_3) <= +inf + 0 <= flow(gasBus_powerplant_gas_coal_2_4) <= +inf + 0 <= flow(gasBus_powerplant_gas_coal_2_5) <= +inf 0 <= InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_0) <= +inf 0 <= InvestmentFlowBlock_total(powerplant_gas_coal_electricityBus_1) <= +inf 0 <= InvestmentFlowBlock_old(powerplant_gas_coal_electricityBus_1) <= +inf diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index e2992856f..c6854d719 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -783,6 +783,7 @@ def test_converter_invest(self): maximum=1000, ep_costs=20, lifetime=20, + fixed_costs=10, ), ), bth: solph.flows.Flow(variable_costs=20), From 672155c35e342476b0f2317967a62ab07a4dbca7 Mon Sep 17 00:00:00 2001 From: "Julian.Endres" Date: Tue, 5 Dec 2023 17:38:11 +0100 Subject: [PATCH 137/180] Fix LP file due to pyomo6.7 changes Former zero floats are now zero integers in the LP file. --- tests/lp_files/dsm_module_oemof_extended.lp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lp_files/dsm_module_oemof_extended.lp b/tests/lp_files/dsm_module_oemof_extended.lp index 3ebe9b458..7d2eda425 100644 --- a/tests/lp_files/dsm_module_oemof_extended.lp +++ b/tests/lp_files/dsm_module_oemof_extended.lp @@ -79,7 +79,7 @@ c_e_SinkDSMOemofBlock_dsm_sum_constraint(demand_dsm_0)_: +0.99 SinkDSMOemofBlock_dsm_up(demand_dsm_0) +0.99 SinkDSMOemofBlock_dsm_up(demand_dsm_1) -1 SinkDSMOemofBlock_dsm_do_shift(demand_dsm_1) -= 0.0 += 0 bounds 0 <= SinkDSMOemofBlock_dsm_do_shift(demand_dsm_0) <= +inf From f998f967ee17a93189c35fe46f76c11735860c3d Mon Sep 17 00:00:00 2001 From: "Julian.Endres" Date: Tue, 5 Dec 2023 22:27:40 +0100 Subject: [PATCH 138/180] Dont detach from black --- src/oemof/solph/flows/_investment_flow_block.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/oemof/solph/flows/_investment_flow_block.py b/src/oemof/solph/flows/_investment_flow_block.py index 464f41ee8..760c58354 100644 --- a/src/oemof/solph/flows/_investment_flow_block.py +++ b/src/oemof/solph/flows/_investment_flow_block.py @@ -1022,9 +1022,7 @@ def _objective_expression(self): self.invest[i, o, p] * m.flows[i, o].investment.fixed_costs[pp] * (1 + m.discount_rate) ** (-pp) - for pp in range( - m.es.periods_years[p], - range_limit) + for pp in range(m.es.periods_years[p], range_limit) ) for i, o in self.EXISTING_INVESTFLOWS: From d5fff12457492cf520aae3607187cec9659e50b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Wed, 6 Dec 2023 16:24:35 +0100 Subject: [PATCH 139/180] Add last time step to Multi-period min/max constraint test --- tests/lp_files/min_max_runtime_multi_period.lp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/lp_files/min_max_runtime_multi_period.lp b/tests/lp_files/min_max_runtime_multi_period.lp index 93438ffa9..6155a7938 100644 --- a/tests/lp_files/min_max_runtime_multi_period.lp +++ b/tests/lp_files/min_max_runtime_multi_period.lp @@ -206,17 +206,20 @@ c_u_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_ c_u_NonConvexFlowBlock_min_uptime_constr(cheap_plant_min_down_constraints_Bus_T_4)_: -2 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_4) +-1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_5) <= 0 c_u_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_3)_: +4 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_2) -3 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) +1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_4) ++1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_5) <= 4 c_u_NonConvexFlowBlock_min_downtime_constr(cheap_plant_min_down_constraints_Bus_T_4)_: +4 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_3) -3 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_4) ++1 NonConvexFlowBlock_status(cheap_plant_min_down_constraints_Bus_T_5) <= 4 bounds From 88ccea742153302e41055ea50c034078029d2dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 7 Dec 2023 10:14:45 +0100 Subject: [PATCH 140/180] Add sequence for up/downtime to Whatsnew --- docs/whatsnew/v0-5-2.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index a8015dc11..7644d1aa6 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -11,6 +11,7 @@ New features * Allow for evaluating differences in the remaining vs. the original value for multi-period investments. +* Allow to define minimum up- and down-time per time step Documentation ############# From 89c0755cf0dda94e035e09d1e4f4d8e900454267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:11:01 +0100 Subject: [PATCH 141/180] Adapt to explicit kwargs in oemof.network The changes also reveals some undiscovered bugs (mostly ignored parameters). This commit does not address these. So, it is expected that tests fail. --- src/oemof/solph/_energy_system.py | 10 +++++++--- src/oemof/solph/buses/_bus.py | 11 ++++++++--- .../experimental/_piecewise_linear_converter.py | 10 +++++----- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 2d889787e..2e90ed1cf 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -76,14 +76,16 @@ def __init__( infer_last_interval=None, periods=None, use_remaining_value=False, - **kwargs, + groupings = None, ): # Doing imports at runtime is generally frowned upon, but should work # for now. See the TODO in :func:`constraint_grouping # ` for more information. from oemof.solph import GROUPINGS - kwargs["groupings"] = GROUPINGS + kwargs.get("groupings", []) + if groupings is None: + groupings = [] + groupings = GROUPINGS + groupings if not ( isinstance(timeindex, pd.DatetimeIndex) @@ -161,7 +163,9 @@ def __init__( raise TypeError(msg) super().__init__( - timeindex=timeindex, timeincrement=timeincrement, **kwargs + groupings=groupings, + timeindex=timeindex, + timeincrement=timeincrement, ) self.periods = periods diff --git a/src/oemof/solph/buses/_bus.py b/src/oemof/solph/buses/_bus.py index 20f97ecaa..73cb33687 100644 --- a/src/oemof/solph/buses/_bus.py +++ b/src/oemof/solph/buses/_bus.py @@ -40,9 +40,14 @@ class Bus(Node): """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.balanced = kwargs.get("balanced", True) + def __init__(self, label=None, *, inputs=None, outputs=None, balanced=True, custom_properties=None): + super().__init__( + label, + inputs=inputs, + outputs=outputs, + custom_properties=custom_properties + ) + self.balanced = balanced def constraint_group(self): if self.balanced: diff --git a/src/oemof/solph/components/experimental/_piecewise_linear_converter.py b/src/oemof/solph/components/experimental/_piecewise_linear_converter.py index 6d6b68c9b..9d08f8cb6 100644 --- a/src/oemof/solph/components/experimental/_piecewise_linear_converter.py +++ b/src/oemof/solph/components/experimental/_piecewise_linear_converter.py @@ -66,12 +66,12 @@ class PiecewiseLinearConverter(Node): PiecewiseLinearConverter'> """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + def __init__(self, label, *, inputs, outputs, conversion_function, in_breakpoints, pw_repn, custom_properties=None): + super().__init__(label, inputs=inputs, outputs=outputs, custom_properties=custom_properties) - self.in_breakpoints = list(kwargs.get("in_breakpoints")) - self.conversion_function = kwargs.get("conversion_function") - self.pw_repn = kwargs.get("pw_repn") + self.in_breakpoints = list(in_breakpoints) + self.conversion_function = conversion_function + self.pw_repn = pw_repn if len(self.inputs) > 1 or len(self.outputs) > 1: raise ValueError( From 53fb7446a9af7884db00824341585ab92193f217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:13:59 +0100 Subject: [PATCH 142/180] Remove label from EnergySystem These labels were just ignored. With explicit kwargs, they cause errors. --- tests/test_models.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_models.py b/tests/test_models.py index 3ac3938eb..b900997a1 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -108,13 +108,13 @@ def test_cellular_structure_detection(): """Test flag creation if list is passed as energysystem to model""" timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H") es = solph.EnergySystem( - label="es", timeindex=timeindex, infer_last_interval=True + timeindex=timeindex, infer_last_interval=True ) ec_1 = solph.EnergySystem( - label="ec_1", timeindex=timeindex, infer_last_interval=True + timeindex=timeindex, infer_last_interval=True ) ec_2 = solph.EnergySystem( - label="ec_2", timeindex=timeindex, infer_last_interval=True + timeindex=timeindex, infer_last_interval=True ) m = solph.Model(energysystem=[es, ec_1, ec_2]) assert m.is_cellular @@ -127,10 +127,10 @@ def test_sub_cell_node_consideration(): """ timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H") es = solph.EnergySystem( - label="es", timeindex=timeindex, infer_last_interval=True + timeindex=timeindex, infer_last_interval=True ) ec_1 = solph.EnergySystem( - label="ec_1", timeindex=timeindex, infer_last_interval=True + timeindex=timeindex, infer_last_interval=True ) bus_es = solph.buses.Bus(label="bus_es") bus_ec_1 = solph.buses.Bus(label="bus_ec_1") @@ -147,10 +147,10 @@ def test_sub_cell_flow_consideration(): """ timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H") es = solph.EnergySystem( - label="es", timeindex=timeindex, infer_last_interval=True + timeindex=timeindex, infer_last_interval=True ) ec_1 = solph.EnergySystem( - label="ec_1", timeindex=timeindex, infer_last_interval=True + timeindex=timeindex, infer_last_interval=True ) bus_es = solph.buses.Bus(label="bus_es") bus_ec_1 = solph.buses.Bus(label="bus_ec_1") From c2017d9b81c2882acb5b348c76db093bd789c288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:15:46 +0100 Subject: [PATCH 143/180] Delete timemode="explicit" from EnergySystem tests At least in the latest versions, the keyword was just ignored. With explicitly named arguments only, it causes errors. --- .../test_solph/test_simple_model/test_simple_dispatch_one.py | 2 +- .../test_simple_dispatch_one_explicit_timemode.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one.py b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one.py index bb4d30d20..99a2f7478 100644 --- a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one.py +++ b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one.py @@ -76,7 +76,7 @@ def test_dispatch_one_time_step(solver="cbc"): conversion_factors={bel: 1 / 3, b_heat_source: (cop - 1) / cop}, ) - energysystem = EnergySystem(timeincrement=[1], timemode="explicit") + energysystem = EnergySystem(timeincrement=[1]) energysystem.add( bgas, bel, diff --git a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one_explicit_timemode.py b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one_explicit_timemode.py index bb4d30d20..99a2f7478 100644 --- a/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one_explicit_timemode.py +++ b/tests/test_scripts/test_solph/test_simple_model/test_simple_dispatch_one_explicit_timemode.py @@ -76,7 +76,7 @@ def test_dispatch_one_time_step(solver="cbc"): conversion_factors={bel: 1 / 3, b_heat_source: (cop - 1) / cop}, ) - energysystem = EnergySystem(timeincrement=[1], timemode="explicit") + energysystem = EnergySystem(timeincrement=[1]) energysystem.add( bgas, bel, From 054666794490f0026fcc45a13340a2b8e8a709a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:24:08 +0100 Subject: [PATCH 144/180] Move to explicit kwargs for GenericCAES --- .../components/experimental/_generic_caes.py | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/oemof/solph/components/experimental/_generic_caes.py b/src/oemof/solph/components/experimental/_generic_caes.py index f150dff5a..b810f37c7 100644 --- a/src/oemof/solph/components/experimental/_generic_caes.py +++ b/src/oemof/solph/components/experimental/_generic_caes.py @@ -97,18 +97,30 @@ class GenericCAES(Node): """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.electrical_input = kwargs.get("electrical_input") - self.fuel_input = kwargs.get("fuel_input") - self.electrical_output = kwargs.get("electrical_output") - self.params = kwargs.get("params") + def __init__( + self,label, *, + electrical_input, + fuel_input, + electrical_output, + params, + custom_properties=None, + ): + super().__init__( + label=label, + inputs=None, + outputs=None, + custom_properties=custom_properties, + ) + + self.electrical_input = electrical_input + self.fuel_input = fuel_input + self.electrical_output = electrical_output + self.params = params # map specific flows to standard API - self.inputs.update(kwargs.get("electrical_input")) - self.inputs.update(kwargs.get("fuel_input")) - self.outputs.update(kwargs.get("electrical_output")) + self.inputs.update(electrical_input) + self.inputs.update(fuel_input) + self.outputs.update(electrical_output) def constraint_group(self): return GenericCAESBlock From 64558a05e56fbe4a69ef3a1f4b2e1c40c6f5d937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:30:34 +0100 Subject: [PATCH 145/180] Remove out_breakpoints from PiecewiseLinearConverter test This parameter was unused and will cause errors with explicit keyword arguments. --- .../test_piecewiselineartransformer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_scripts/test_solph/test_piecewiselineartransformer/test_piecewiselineartransformer.py b/tests/test_scripts/test_solph/test_piecewiselineartransformer/test_piecewiselineartransformer.py index 19a89ad27..41b7a60b1 100644 --- a/tests/test_scripts/test_solph/test_piecewiselineartransformer/test_piecewiselineartransformer.py +++ b/tests/test_scripts/test_solph/test_piecewiselineartransformer/test_piecewiselineartransformer.py @@ -48,7 +48,6 @@ def conv_func(x): return 0.01 * x**2 in_breakpoints = np.arange(0, 110, 25) - out_breakpoints = conv_func(in_breakpoints) # Create and add PiecewiseLinearConverter pwltf = solph.components.experimental.PiecewiseLinearConverter( @@ -56,7 +55,6 @@ def conv_func(x): inputs={b_gas: solph.flows.Flow(nominal_value=100, variable_costs=1)}, outputs={b_el: solph.flows.Flow()}, in_breakpoints=in_breakpoints, - out_breakpoints=out_breakpoints, conversion_function=conv_func, pw_repn="CC", ) From 725ea78795a6c763a920b732bb90eabcf1fa8ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:31:03 +0100 Subject: [PATCH 146/180] Switch to explicit named arguments for ElectricalBus --- .../buses/experimental/_electrical_bus.py | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/oemof/solph/buses/experimental/_electrical_bus.py b/src/oemof/solph/buses/experimental/_electrical_bus.py index fe53b56e3..eeeae2a88 100644 --- a/src/oemof/solph/buses/experimental/_electrical_bus.py +++ b/src/oemof/solph/buses/experimental/_electrical_bus.py @@ -47,8 +47,23 @@ class ElectricalBus(Bus): """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.slack = kwargs.get("slack", False) - self.v_max = kwargs.get("v_max", 1000) - self.v_min = kwargs.get("v_min", -1000) + def __init__( + self, + label=None, + *, + v_max, + v_min, + inputs=None, + outputs=None, + custom_properties=None, + slack=False, + ): + super().__init__( + label, + inputs=inputs, + outputs=outputs, + custom_properties=custom_properties, + ) + self.slack = slack + self.v_max = v_max + self.v_min = v_min From 8332e93ce69e932028318afce2a619964d1f861e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:47:32 +0100 Subject: [PATCH 147/180] Fix handing Converter's custom_attributes to network.Node --- src/oemof/solph/components/_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oemof/solph/components/_converter.py b/src/oemof/solph/components/_converter.py index a2e9a559b..b84b94797 100644 --- a/src/oemof/solph/components/_converter.py +++ b/src/oemof/solph/components/_converter.py @@ -117,7 +117,7 @@ def __init__( label=label, inputs=inputs, outputs=outputs, - **custom_attributes, + custom_properties=custom_attributes, ) if conversion_factors is None: From 8cb2cf18eb7f08536bb95b822f9feb1bc32ac745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:52:23 +0100 Subject: [PATCH 148/180] Fix initialisation of Link The warnings need the network.Node to be initialised already. --- src/oemof/solph/components/_link.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/oemof/solph/components/_link.py b/src/oemof/solph/components/_link.py index f48a04209..ba92b4a21 100644 --- a/src/oemof/solph/components/_link.py +++ b/src/oemof/solph/components/_link.py @@ -86,6 +86,12 @@ def __init__( conversion_factors=None, custom_attributes=None, ): + super().__init__( + label, + inputs=inputs, + outputs=outputs, + custom_properties=custom_attributes, + ) if inputs is None: warn_if_missing_attribute(self, "inputs") inputs = {} @@ -97,12 +103,6 @@ def __init__( conversion_factors = {} if custom_attributes is None: custom_attributes = {} - super().__init__( - label=label, - inputs=inputs, - outputs=outputs, - **custom_attributes, - ) self.conversion_factors = { k: sequence(v) for k, v in conversion_factors.items() } From 8ead2b335cc86b4abf6dbb25eff2b7b12821dd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 20:58:12 +0100 Subject: [PATCH 149/180] Fix handing custom_properties of GenericStorage to network.Node --- src/oemof/solph/components/_generic_storage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/oemof/solph/components/_generic_storage.py b/src/oemof/solph/components/_generic_storage.py index adfadd2b7..d1731ee1d 100644 --- a/src/oemof/solph/components/_generic_storage.py +++ b/src/oemof/solph/components/_generic_storage.py @@ -193,10 +193,10 @@ def __init__( if custom_attributes is None: custom_attributes = {} super().__init__( - label=label, + label, inputs=inputs, outputs=outputs, - **custom_attributes, + custom_properties=custom_attributes, ) # --- BEGIN: The following code can be removed for versions >= v0.6 --- if investment is not None: From 213b1644071ebb6163d6a4e84ccab01f6fa28d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 15 Dec 2023 21:07:13 +0100 Subject: [PATCH 150/180] Adhere to Black --- src/oemof/solph/_energy_system.py | 2 +- src/oemof/solph/buses/_bus.py | 12 ++++++-- .../components/experimental/_generic_caes.py | 4 ++- .../_piecewise_linear_converter.py | 19 +++++++++++-- tests/test_models.py | 28 +++++-------------- 5 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/oemof/solph/_energy_system.py b/src/oemof/solph/_energy_system.py index 2e90ed1cf..234080a07 100644 --- a/src/oemof/solph/_energy_system.py +++ b/src/oemof/solph/_energy_system.py @@ -76,7 +76,7 @@ def __init__( infer_last_interval=None, periods=None, use_remaining_value=False, - groupings = None, + groupings=None, ): # Doing imports at runtime is generally frowned upon, but should work # for now. See the TODO in :func:`constraint_grouping diff --git a/src/oemof/solph/buses/_bus.py b/src/oemof/solph/buses/_bus.py index 73cb33687..8a1710e08 100644 --- a/src/oemof/solph/buses/_bus.py +++ b/src/oemof/solph/buses/_bus.py @@ -40,12 +40,20 @@ class Bus(Node): """ - def __init__(self, label=None, *, inputs=None, outputs=None, balanced=True, custom_properties=None): + def __init__( + self, + label=None, + *, + inputs=None, + outputs=None, + balanced=True, + custom_properties=None, + ): super().__init__( label, inputs=inputs, outputs=outputs, - custom_properties=custom_properties + custom_properties=custom_properties, ) self.balanced = balanced diff --git a/src/oemof/solph/components/experimental/_generic_caes.py b/src/oemof/solph/components/experimental/_generic_caes.py index b810f37c7..8af708162 100644 --- a/src/oemof/solph/components/experimental/_generic_caes.py +++ b/src/oemof/solph/components/experimental/_generic_caes.py @@ -98,7 +98,9 @@ class GenericCAES(Node): """ def __init__( - self,label, *, + self, + label, + *, electrical_input, fuel_input, electrical_output, diff --git a/src/oemof/solph/components/experimental/_piecewise_linear_converter.py b/src/oemof/solph/components/experimental/_piecewise_linear_converter.py index 9d08f8cb6..c58e705b4 100644 --- a/src/oemof/solph/components/experimental/_piecewise_linear_converter.py +++ b/src/oemof/solph/components/experimental/_piecewise_linear_converter.py @@ -66,8 +66,23 @@ class PiecewiseLinearConverter(Node): PiecewiseLinearConverter'> """ - def __init__(self, label, *, inputs, outputs, conversion_function, in_breakpoints, pw_repn, custom_properties=None): - super().__init__(label, inputs=inputs, outputs=outputs, custom_properties=custom_properties) + def __init__( + self, + label, + *, + inputs, + outputs, + conversion_function, + in_breakpoints, + pw_repn, + custom_properties=None, + ): + super().__init__( + label, + inputs=inputs, + outputs=outputs, + custom_properties=custom_properties, + ) self.in_breakpoints = list(in_breakpoints) self.conversion_function = conversion_function diff --git a/tests/test_models.py b/tests/test_models.py index b900997a1..eb18d7e50 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -107,15 +107,9 @@ def test_multi_period_default_discount_rate(): def test_cellular_structure_detection(): """Test flag creation if list is passed as energysystem to model""" timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H") - es = solph.EnergySystem( - timeindex=timeindex, infer_last_interval=True - ) - ec_1 = solph.EnergySystem( - timeindex=timeindex, infer_last_interval=True - ) - ec_2 = solph.EnergySystem( - timeindex=timeindex, infer_last_interval=True - ) + es = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True) + ec_1 = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True) + ec_2 = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True) m = solph.Model(energysystem=[es, ec_1, ec_2]) assert m.is_cellular @@ -126,12 +120,8 @@ def test_sub_cell_node_consideration(): energysystems. """ timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H") - es = solph.EnergySystem( - timeindex=timeindex, infer_last_interval=True - ) - ec_1 = solph.EnergySystem( - timeindex=timeindex, infer_last_interval=True - ) + es = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True) + ec_1 = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True) bus_es = solph.buses.Bus(label="bus_es") bus_ec_1 = solph.buses.Bus(label="bus_ec_1") es.add(bus_es) @@ -146,12 +136,8 @@ def test_sub_cell_flow_consideration(): energysystems. """ timeindex = pd.date_range(start="2020-01-01", periods=1, freq="H") - es = solph.EnergySystem( - timeindex=timeindex, infer_last_interval=True - ) - ec_1 = solph.EnergySystem( - timeindex=timeindex, infer_last_interval=True - ) + es = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True) + ec_1 = solph.EnergySystem(timeindex=timeindex, infer_last_interval=True) bus_es = solph.buses.Bus(label="bus_es") bus_ec_1 = solph.buses.Bus(label="bus_ec_1") es.add(bus_es) From 523654a2c7047a333c0d3e91e42d9860035078bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Sat, 16 Dec 2023 19:56:18 +0100 Subject: [PATCH 151/180] Maintain compatibility with network v0.5.0a5 --- src/oemof/solph/buses/_bus.py | 4 ++++ src/oemof/solph/components/_link.py | 12 ++++++------ .../solph/components/experimental/_generic_caes.py | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/oemof/solph/buses/_bus.py b/src/oemof/solph/buses/_bus.py index 8a1710e08..98cf88787 100644 --- a/src/oemof/solph/buses/_bus.py +++ b/src/oemof/solph/buses/_bus.py @@ -49,6 +49,10 @@ def __init__( balanced=True, custom_properties=None, ): + if inputs is None: + inputs = {} + if outputs is None: + outputs = {} super().__init__( label, inputs=inputs, diff --git a/src/oemof/solph/components/_link.py b/src/oemof/solph/components/_link.py index ba92b4a21..869677c13 100644 --- a/src/oemof/solph/components/_link.py +++ b/src/oemof/solph/components/_link.py @@ -86,12 +86,6 @@ def __init__( conversion_factors=None, custom_attributes=None, ): - super().__init__( - label, - inputs=inputs, - outputs=outputs, - custom_properties=custom_attributes, - ) if inputs is None: warn_if_missing_attribute(self, "inputs") inputs = {} @@ -103,6 +97,12 @@ def __init__( conversion_factors = {} if custom_attributes is None: custom_attributes = {} + super().__init__( + label, + inputs=inputs, + outputs=outputs, + custom_properties=custom_attributes, + ) self.conversion_factors = { k: sequence(v) for k, v in conversion_factors.items() } diff --git a/src/oemof/solph/components/experimental/_generic_caes.py b/src/oemof/solph/components/experimental/_generic_caes.py index 8af708162..53f667edc 100644 --- a/src/oemof/solph/components/experimental/_generic_caes.py +++ b/src/oemof/solph/components/experimental/_generic_caes.py @@ -109,8 +109,8 @@ def __init__( ): super().__init__( label=label, - inputs=None, - outputs=None, + inputs={}, + outputs={}, custom_properties=custom_properties, ) From b40371236fa05edc341d259ebec6e49c7a7b1280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Mon, 18 Dec 2023 19:31:44 +0100 Subject: [PATCH 152/180] Fix inialisation of link class To access e.g. .label, warn_ helpers need oemof.network.Entity to be initialised first. --- src/oemof/solph/components/_link.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/oemof/solph/components/_link.py b/src/oemof/solph/components/_link.py index 869677c13..6e0155df7 100644 --- a/src/oemof/solph/components/_link.py +++ b/src/oemof/solph/components/_link.py @@ -86,15 +86,11 @@ def __init__( conversion_factors=None, custom_attributes=None, ): + # compatibility with omeof.network w/o explicit named arguments if inputs is None: - warn_if_missing_attribute(self, "inputs") inputs = {} if outputs is None: - warn_if_missing_attribute(self, "outputs") outputs = {} - if conversion_factors is None: - warn_if_missing_attribute(self, "conversion_factors") - conversion_factors = {} if custom_attributes is None: custom_attributes = {} super().__init__( @@ -103,6 +99,13 @@ def __init__( outputs=outputs, custom_properties=custom_attributes, ) + if not inputs: + warn_if_missing_attribute(self, "inputs") + if not outputs: + warn_if_missing_attribute(self, "outputs") + if conversion_factors is None: + warn_if_missing_attribute(self, "conversion_factors") + conversion_factors = {} self.conversion_factors = { k: sequence(v) for k, v in conversion_factors.items() } From 84693ddeaa919bff02683f7237931df2d8de94da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Tue, 19 Dec 2023 10:21:19 +0100 Subject: [PATCH 153/180] Do not double-set label in Converter The label seems to be set to allow calling workaround before Node is initialised. --- src/oemof/solph/components/_converter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/oemof/solph/components/_converter.py b/src/oemof/solph/components/_converter.py index b84b94797..04044836f 100644 --- a/src/oemof/solph/components/_converter.py +++ b/src/oemof/solph/components/_converter.py @@ -101,13 +101,9 @@ def __init__( conversion_factors=None, custom_attributes=None, ): - self.label = label - if inputs is None: - warn_if_missing_attribute(self, "inputs") inputs = {} if outputs is None: - warn_if_missing_attribute(self, "outputs") outputs = {} if custom_attributes is None: @@ -119,6 +115,10 @@ def __init__( outputs=outputs, custom_properties=custom_attributes, ) + if not inputs: + warn_if_missing_attribute(self, "inputs") + if not outputs: + warn_if_missing_attribute(self, "outputs") if conversion_factors is None: conversion_factors = {} From 3196ef765d601bc96091a7d13a35d396f040d489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Tue, 19 Dec 2023 11:21:38 +0100 Subject: [PATCH 154/180] Dactivate ElectricalLine test ElectricalLine seems to be added to the EnergySystem as if it was a Node. This, however, is no longer possible as Flows do not have 'inputs'. --- .../test_scripts/test_solph/test_lopf/test_lopf.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/test_scripts/test_solph/test_lopf/test_lopf.py b/tests/test_scripts/test_solph/test_lopf/test_lopf.py index 740ed47d9..80a3a7660 100644 --- a/tests/test_scripts/test_solph/test_lopf/test_lopf.py +++ b/tests/test_scripts/test_solph/test_lopf/test_lopf.py @@ -29,6 +29,7 @@ from oemof.solph.flows import experimental as exp_flow +@pytest.mark.skip(reason="Constraints of Electrical Line do not build.") def test_lopf(solver="cbc"): logging.info("Initialize the energy system") @@ -50,8 +51,7 @@ def test_lopf(solver="cbc"): es.add(b_el0, b_el1, b_el2) - es.add( - exp_flow.ElectricalLine( + b_el1.inputs[b_el0] = exp_flow.ElectricalLine( input=b_el0, output=b_el1, reactance=0.0001, @@ -59,10 +59,8 @@ def test_lopf(solver="cbc"): min=-1, max=1, ) - ) - es.add( - exp_flow.ElectricalLine( + b_el2.inputs[b_el1] = exp_flow.ElectricalLine( input=b_el1, output=b_el2, reactance=0.0001, @@ -70,17 +68,14 @@ def test_lopf(solver="cbc"): min=-1, max=1, ) - ) - es.add( - exp_flow.ElectricalLine( + b_el0.inputs[b_el2] = exp_flow.ElectricalLine( input=b_el2, output=b_el0, reactance=0.0001, nominal_value=60, min=-1, max=1, - ) ) es.add( From f8131da2946d2388fcaff9f220b82e5bc0896b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Tue, 19 Dec 2023 11:23:26 +0100 Subject: [PATCH 155/180] Adhere to Black --- .../test_solph/test_lopf/test_lopf.py | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/test_scripts/test_solph/test_lopf/test_lopf.py b/tests/test_scripts/test_solph/test_lopf/test_lopf.py index 80a3a7660..26b2a1fa6 100644 --- a/tests/test_scripts/test_solph/test_lopf/test_lopf.py +++ b/tests/test_scripts/test_solph/test_lopf/test_lopf.py @@ -52,30 +52,30 @@ def test_lopf(solver="cbc"): es.add(b_el0, b_el1, b_el2) b_el1.inputs[b_el0] = exp_flow.ElectricalLine( - input=b_el0, - output=b_el1, - reactance=0.0001, - nominal_value=Investment(ep_costs=10), - min=-1, - max=1, - ) + input=b_el0, + output=b_el1, + reactance=0.0001, + nominal_value=Investment(ep_costs=10), + min=-1, + max=1, + ) b_el2.inputs[b_el1] = exp_flow.ElectricalLine( - input=b_el1, - output=b_el2, - reactance=0.0001, - nominal_value=60, - min=-1, - max=1, - ) + input=b_el1, + output=b_el2, + reactance=0.0001, + nominal_value=60, + min=-1, + max=1, + ) b_el0.inputs[b_el2] = exp_flow.ElectricalLine( - input=b_el2, - output=b_el0, - reactance=0.0001, - nominal_value=60, - min=-1, - max=1, + input=b_el2, + output=b_el0, + reactance=0.0001, + nominal_value=60, + min=-1, + max=1, ) es.add( From 8b5f511ea80c08292d16a79ac1cb83adafbc0274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 09:58:28 +0100 Subject: [PATCH 156/180] Move to latest revision of action setup-python The old versions are no longer suported. --- .github/workflows/lint.yml | 2 +- .github/workflows/packaging.yml | 2 +- .github/workflows/tox_checks.yml | 2 +- .github/workflows/tox_pytests.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6f68dba4a..8a4a7fff9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Python - uses: actions/setup-python@v1 + uses: actions/setup-python@v5 with: python-version: 3.9 diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index b3601dfb9..874a5bfb7 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/tox_checks.yml b/.github/workflows/tox_checks.yml index 8686b132f..f575ed022 100644 --- a/.github/workflows/tox_checks.yml +++ b/.github/workflows/tox_checks.yml @@ -33,7 +33,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Python ${{ env.default_python || '3.9' }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: "${{ env.default_python || '3.9' }}" diff --git a/.github/workflows/tox_pytests.yml b/.github/workflows/tox_pytests.yml index dc777a7f9..7b7570226 100644 --- a/.github/workflows/tox_pytests.yml +++ b/.github/workflows/tox_pytests.yml @@ -23,7 +23,7 @@ jobs: - name: Install cbc run: sudo apt install coinor-cbc - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From a4da44dc398b235b49da59248a0e741ad192e5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 10:23:05 +0100 Subject: [PATCH 157/180] Remove upper bound for setuptools Editable builds using pyroject.toml were introduced with PEP-660. It is supported since setuptools 64. It was still possible using legacy mode (setup.py) but led to warnings. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bbde2c90f..8d7102f4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,5 +19,5 @@ exclude = ''' ''' [build-system] -requires = ["setuptools<60.0", "wheel"] +requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" From 87dad136a12158fafd2696b57aaa2cfd9ca2c77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 10:40:10 +0100 Subject: [PATCH 158/180] Use current solph API in tests FutureWarnings should be eliminated now, ExperimentalFeatureWarnings and SuspiciousUsageWarnings remain as we test experimental features. --- tests/constraint_tests.py | 8 +++--- tests/multi_period_constraint_tests.py | 35 ++++++++++++-------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/tests/constraint_tests.py b/tests/constraint_tests.py index 4738fe8d0..74aa3c8a1 100644 --- a/tests/constraint_tests.py +++ b/tests/constraint_tests.py @@ -36,7 +36,9 @@ def setup_class(cls): def setup_method(self): self.energysystem = solph.EnergySystem( - groupings=solph.GROUPINGS, timeindex=self.date_time_index + groupings=solph.GROUPINGS, + timeindex=self.date_time_index, + infer_last_interval=True, ) def get_om(self): @@ -1862,8 +1864,8 @@ def test_integral_limit_error_no_multi_period(self): om, keyword="space" ) - def test_summed_min_max_source(self): - """Constraints test summed_min and summed_max attribute of flow""" + def test_full_load_time_min_max_source(self): + """Constraints test full_load_time_min and full_load_time_max attribute of flow""" bel = solph.buses.Bus(label="electricityBus") diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index 6394e8a52..646ccb892 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -160,7 +160,7 @@ def test_linear_converter_invest_remaining_value(self): outputs={ bel: solph.flows.Flow( variable_costs=50, - investment=solph.Investment( + nominal_value=solph.Investment( existing=50, maximum=1000, overall_maximum=10000, @@ -266,7 +266,7 @@ def test_nominal_value_to_zero(self): self.compare_lp_files("nominal_value_to_zero_multi_period.lp") def test_fixed_source_invest_sink(self): - """Constraints test for fixed source + invest sink w. `summed_max`""" + """Constraints test for fixed source + invest sink w. `full_load_time_max`""" bel = solph.buses.Bus(label="electricityBus") source = solph.components.Source( @@ -282,7 +282,7 @@ def test_fixed_source_invest_sink(self): label="excess", inputs={ bel: solph.flows.Flow( - summed_max=2.3, + full_load_time_max=2.3, variable_costs=25, max=0.8, nominal_value=solph.Investment( @@ -407,7 +407,6 @@ def test_storage_invest_1_remaining_value(self): label="storage1", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -417,7 +416,7 @@ def test_storage_invest_1_remaining_value(self): lifetime_outflow=20, inflow_conversion_factor=0.97, outflow_conversion_factor=0.86, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=[145, 130, 115], maximum=234, lifetime=20, @@ -1930,7 +1929,6 @@ def test_nonconvex_investment_storage_without_offset_remaining_value(self): label="storage_non_convex", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -1940,7 +1938,7 @@ def test_nonconvex_investment_storage_without_offset_remaining_value(self): outflow_conversion_factor=0.86, lifetime_inflow=20, lifetime_outflow=20, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=141, maximum=244, minimum=12, @@ -1996,7 +1994,6 @@ def test_nonconvex_investment_storage_with_offset_remaining_value(self): label="storage_non_convex", inputs={bel: solph.flows.Flow(variable_costs=56)}, outputs={bel: solph.flows.Flow(variable_costs=24)}, - nominal_storage_capacity=None, loss_rate=0.13, max_storage_level=0.9, min_storage_level=0.1, @@ -2006,7 +2003,7 @@ def test_nonconvex_investment_storage_with_offset_remaining_value(self): outflow_conversion_factor=0.86, lifetime_inflow=20, lifetime_outflow=20, - investment=solph.Investment( + nominal_storage_capacity=solph.Investment( ep_costs=145, minimum=19, offset=5, @@ -2072,7 +2069,7 @@ def test_nonconvex_invest_sink_without_offset(self): label="sink_nonconvex_invest", inputs={ bel: solph.flows.Flow( - summed_max=2.3, + full_load_time_max=2.3, variable_costs=25, max=0.8, nominal_value=solph.Investment( @@ -2096,10 +2093,10 @@ def test_nonconvex_invest_sink_without_offset_remaining_value(self): label="sink_nonconvex_invest", inputs={ bel: solph.flows.Flow( - summed_max=2.3, + full_load_time_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, minimum=15, nonconvex=True, @@ -2124,7 +2121,7 @@ def test_nonconvex_invest_source_with_offset(self): label="source_nonconvex_invest", outputs={ bel: solph.flows.Flow( - summed_max=2.3, + full_load_time_max=2.3, variable_costs=25, max=0.8, nominal_value=solph.Investment( @@ -2149,10 +2146,10 @@ def test_nonconvex_invest_source_with_offset_remaining_value(self): label="source_nonconvex_invest", outputs={ bel: solph.flows.Flow( - summed_max=2.3, + full_load_time_max=2.3, variable_costs=25, max=0.8, - investment=solph.Investment( + nominal_value=solph.Investment( ep_costs=500, minimum=15, maximum=20, @@ -2178,7 +2175,7 @@ def test_nonconvex_invest_source_with_offset_no_minimum(self): label="source_nonconvex_invest", outputs={ bel: solph.flows.Flow( - summed_max=2.3, + full_load_time_max=2.3, variable_costs=25, max=0.8, nominal_value=solph.Investment( @@ -2197,15 +2194,15 @@ def test_nonconvex_invest_source_with_offset_no_minimum(self): ) def test_summed_min_max_source(self): - """Test sink with summed_min and summed_max attribute""" + """Test sink with full_load_time_min and full_load_time_max attribute""" bel = solph.buses.Bus(label="electricityBus") sink = solph.components.Sink( label="excess", inputs={ bel: solph.flows.Flow( - summed_min=3, - summed_max=100, + full_load_time_min=3, + full_load_time_max=100, variable_costs=25, max=0.8, nominal_value=10, From def691398a8dba66a7ffbf747397d6f6e001d2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 10:44:20 +0100 Subject: [PATCH 159/180] Update to current pytest API --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 889fafe6e..8354fec39 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,7 @@ python_files = tests.py addopts = -ra - --strict + --strict-markers --ignore=docs/conf.py --ignore=setup.py --ignore=ci From cfa17063429ea0f14314ebcebbb5f135f38077d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 10:47:35 +0100 Subject: [PATCH 160/180] Fix long lines --- tests/constraint_tests.py | 2 +- tests/multi_period_constraint_tests.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/constraint_tests.py b/tests/constraint_tests.py index 74aa3c8a1..c5be91e1f 100644 --- a/tests/constraint_tests.py +++ b/tests/constraint_tests.py @@ -1865,7 +1865,7 @@ def test_integral_limit_error_no_multi_period(self): ) def test_full_load_time_min_max_source(self): - """Constraints test full_load_time_min and full_load_time_max attribute of flow""" + """Constraints test full_load_time_min and _max attribute of flow""" bel = solph.buses.Bus(label="electricityBus") diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index 646ccb892..8c4f60cc4 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -266,7 +266,8 @@ def test_nominal_value_to_zero(self): self.compare_lp_files("nominal_value_to_zero_multi_period.lp") def test_fixed_source_invest_sink(self): - """Constraints test for fixed source + invest sink w. `full_load_time_max`""" + """Constraints test for fixed source + invest sink w. + `full_load_time_max`""" bel = solph.buses.Bus(label="electricityBus") source = solph.components.Source( @@ -2194,7 +2195,7 @@ def test_nonconvex_invest_source_with_offset_no_minimum(self): ) def test_summed_min_max_source(self): - """Test sink with full_load_time_min and full_load_time_max attribute""" + """Test sink with full_load_time_min and _max attribute""" bel = solph.buses.Bus(label="electricityBus") sink = solph.components.Sink( From 353724e8c5dbfd996e1f227375a252ab81f72468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 11:05:23 +0100 Subject: [PATCH 161/180] Use current solph API in docsting examples --- src/oemof/solph/constraints/equate_variables.py | 7 +++++-- src/oemof/solph/constraints/integral_limit.py | 7 +++++-- src/oemof/solph/constraints/investment_limit.py | 7 +++++-- src/oemof/solph/constraints/shared_limit.py | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/oemof/solph/constraints/equate_variables.py b/src/oemof/solph/constraints/equate_variables.py index 5ce350da4..53d5f3e7e 100644 --- a/src/oemof/solph/constraints/equate_variables.py +++ b/src/oemof/solph/constraints/equate_variables.py @@ -62,8 +62,11 @@ def equate_variables(model, var1, var2, factor1=1, name=None): >>> import pandas as pd >>> from oemof import solph - >>> date_time_index = pd.date_range('1/1/2012', periods=5, freq='H') - >>> energysystem = solph.EnergySystem(timeindex=date_time_index) + >>> date_time_index = pd.date_range('1/1/2012', periods=6, freq='H') + >>> energysystem = solph.EnergySystem( + ... timeindex=date_time_index, + ... infer_last_interval=False, + ... ) >>> bel1 = solph.buses.Bus(label='electricity1') >>> bel2 = solph.buses.Bus(label='electricity2') >>> energysystem.add(bel1, bel2) diff --git a/src/oemof/solph/constraints/integral_limit.py b/src/oemof/solph/constraints/integral_limit.py index 28fe427b6..e5157e5b7 100644 --- a/src/oemof/solph/constraints/integral_limit.py +++ b/src/oemof/solph/constraints/integral_limit.py @@ -102,8 +102,11 @@ def generic_integral_limit(om, keyword, flows=None, limit=None): -------- >>> import pandas as pd >>> from oemof import solph - >>> date_time_index = pd.date_range('1/1/2012', periods=5, freq='H') - >>> energysystem = solph.EnergySystem(timeindex=date_time_index) + >>> date_time_index = pd.date_range('1/1/2012', periods=6, freq='H') + >>> energysystem = solph.EnergySystem( + ... timeindex=date_time_index, + ... infer_last_interval=False, + ... ) >>> bel = solph.buses.Bus(label='electricityBus') >>> flow1 = solph.flows.Flow( ... nominal_value=100, diff --git a/src/oemof/solph/constraints/investment_limit.py b/src/oemof/solph/constraints/investment_limit.py index 078b553b1..f2a44a955 100644 --- a/src/oemof/solph/constraints/investment_limit.py +++ b/src/oemof/solph/constraints/investment_limit.py @@ -171,8 +171,11 @@ def additional_investment_flow_limit(model, keyword, limit=None): -------- >>> import pandas as pd >>> from oemof import solph - >>> date_time_index = pd.date_range('1/1/2020', periods=5, freq='H') - >>> es = solph.EnergySystem(timeindex=date_time_index) + >>> date_time_index = pd.date_range('1/1/2020', periods=6, freq='H') + >>> es = solph.EnergySystem( + ... timeindex=date_time_index, + ... infer_last_interval=False, + ... ) >>> bus = solph.buses.Bus(label='bus_1') >>> sink = solph.components.Sink(label="sink", inputs={bus: ... solph.flows.Flow(nominal_value=10, fix=[10, 20, 30, 40, 50])}) diff --git a/src/oemof/solph/constraints/shared_limit.py b/src/oemof/solph/constraints/shared_limit.py index 4cf055b8b..e85a3abab 100644 --- a/src/oemof/solph/constraints/shared_limit.py +++ b/src/oemof/solph/constraints/shared_limit.py @@ -60,8 +60,11 @@ def shared_limit( >>> import pandas as pd >>> from oemof import solph - >>> date_time_index = pd.date_range('1/1/2012', periods=5, freq='H') - >>> energysystem = solph.EnergySystem(timeindex=date_time_index) + >>> date_time_index = pd.date_range('1/1/2012', periods=6, freq='H') + >>> energysystem = solph.EnergySystem( + ... timeindex=date_time_index, + ... infer_last_interval=False, + ... ) >>> b1 = solph.buses.Bus(label="Party1Bus") >>> b2 = solph.buses.Bus(label="Party2Bus") >>> storage1 = solph.components.GenericStorage( From e340c55402cb1b54553e0a39f737922ad1b85024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:04:16 +0100 Subject: [PATCH 162/180] Silence corresponding warning in tests of experimental features --- tests/multi_period_constraint_tests.py | 2 ++ tests/test_energy_system.py | 5 +++++ tests/test_models.py | 3 ++- .../test_multi_period_dispatch_model.py | 3 +++ .../test_multi_period_investment_model.py | 3 +++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index 8c4f60cc4..8cabf2a7e 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -22,6 +22,8 @@ logging.disable(logging.INFO) +@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") +@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") class TestsMultiPeriodConstraint: @classmethod def setup_class(cls): diff --git a/tests/test_energy_system.py b/tests/test_energy_system.py index 7828f31dd..8aca373a8 100644 --- a/tests/test_energy_system.py +++ b/tests/test_energy_system.py @@ -8,10 +8,13 @@ """ import pandas as pd +import pytest from oemof.solph import EnergySystem +@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") +@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") def test_add_periods(): """test method _add_periods of energy system""" timeindex = pd.date_range(start="2012-01-01", periods=10000, freq="H") @@ -31,6 +34,8 @@ def test_add_periods(): ) +@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") +@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") def test_extract_periods_years(): """test method _extract_periods_years of energy system""" t_idx_1 = pd.date_range("1/1/2020", periods=3, freq="H").to_series() diff --git a/tests/test_models.py b/tests/test_models.py index 3ac3938eb..f5439f48b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -68,9 +68,10 @@ def test_infeasible_model(): solph.processing.meta_results(m) +@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") +@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") def test_multi_period_default_discount_rate(): """Test error being thrown for default multi-period discount rate""" - warnings.filterwarnings("ignore", category=FutureWarning) timeindex = pd.date_range(start="2017-01-01", periods=100, freq="D") es = solph.EnergySystem( timeindex=timeindex, diff --git a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py index 0d2ffec5c..92000187b 100644 --- a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py +++ b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py @@ -15,6 +15,7 @@ """ import pandas as pd +import pytest from oemof.solph import EnergySystem from oemof.solph import Model @@ -25,6 +26,8 @@ from oemof.solph import views +@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") +@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") def test_multi_period_dispatch_model(solver="cbc"): """Test a simple multi_period dispatch model""" diff --git a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py index ccf3e3b91..42172ceaf 100644 --- a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py +++ b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py @@ -15,6 +15,7 @@ """ import pandas as pd +import pytest from oemof.solph import EnergySystem from oemof.solph import Model @@ -26,6 +27,8 @@ from oemof.solph import views +@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") +@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") def test_multi_period_investment_model(solver="cbc"): """Test a simple multi_period investment model for multiple SinkDSM approaches""" From e6fea2ff94b68d59ba530ce5e0635ce8558f5e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:08:52 +0100 Subject: [PATCH 163/180] Silence SuspiciousUsageWarning in multi-period tests --- tests/multi_period_constraint_tests.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index 8cabf2a7e..13b0e83d3 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -21,9 +21,12 @@ logging.disable(logging.INFO) - +# Warnings about the fature being experimental: @pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") @pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") +# Warnings about default parameters beaing used: +@pytest.mark.filterwarnings("ignore:You did not specify an interest rate.:UserWarning") +@pytest.mark.filterwarnings("ignore:By default, a discount_rate of 0.02 is used for a multi-period model.:UserWarning") class TestsMultiPeriodConstraint: @classmethod def setup_class(cls): @@ -2249,6 +2252,7 @@ def test_flow_reaching_lifetime_initial_age(self): self.energysystem.add(bel, sink) self.compare_lp_files("flow_reaching_lifetime_initial_age.lp") + @pytest.mark.filterwarnings("ignore:Be aware that the fixed costs attribute is only:UserWarning") def test_fixed_costs(self): """Test fixed_cost attribute for different kinds of flows""" bel = solph.buses.Bus(label="electricityBus") From 98ede528dc35fb739a6d891a969d010cac746bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:09:16 +0100 Subject: [PATCH 164/180] Adhere to Black --- tests/multi_period_constraint_tests.py | 21 ++++++++++++++----- tests/test_energy_system.py | 16 ++++++++++---- tests/test_models.py | 8 +++++-- .../test_multi_period_dispatch_model.py | 8 +++++-- .../test_multi_period_investment_model.py | 8 +++++-- 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index 13b0e83d3..dfd483e77 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -21,12 +21,21 @@ logging.disable(logging.INFO) + # Warnings about the fature being experimental: -@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") -@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") +@pytest.mark.filterwarnings( + "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" +) +@pytest.mark.filterwarnings( + "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" +) # Warnings about default parameters beaing used: -@pytest.mark.filterwarnings("ignore:You did not specify an interest rate.:UserWarning") -@pytest.mark.filterwarnings("ignore:By default, a discount_rate of 0.02 is used for a multi-period model.:UserWarning") +@pytest.mark.filterwarnings( + "ignore:You did not specify an interest rate.:UserWarning" +) +@pytest.mark.filterwarnings( + "ignore:By default, a discount_rate of 0.02 is used for a multi-period model.:UserWarning" +) class TestsMultiPeriodConstraint: @classmethod def setup_class(cls): @@ -2252,7 +2261,9 @@ def test_flow_reaching_lifetime_initial_age(self): self.energysystem.add(bel, sink) self.compare_lp_files("flow_reaching_lifetime_initial_age.lp") - @pytest.mark.filterwarnings("ignore:Be aware that the fixed costs attribute is only:UserWarning") + @pytest.mark.filterwarnings( + "ignore:Be aware that the fixed costs attribute is only:UserWarning" + ) def test_fixed_costs(self): """Test fixed_cost attribute for different kinds of flows""" bel = solph.buses.Bus(label="electricityBus") diff --git a/tests/test_energy_system.py b/tests/test_energy_system.py index 8aca373a8..a4012f91f 100644 --- a/tests/test_energy_system.py +++ b/tests/test_energy_system.py @@ -13,8 +13,12 @@ from oemof.solph import EnergySystem -@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") -@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") +@pytest.mark.filterwarnings( + "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" +) +@pytest.mark.filterwarnings( + "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" +) def test_add_periods(): """test method _add_periods of energy system""" timeindex = pd.date_range(start="2012-01-01", periods=10000, freq="H") @@ -34,8 +38,12 @@ def test_add_periods(): ) -@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") -@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") +@pytest.mark.filterwarnings( + "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" +) +@pytest.mark.filterwarnings( + "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" +) def test_extract_periods_years(): """test method _extract_periods_years of energy system""" t_idx_1 = pd.date_range("1/1/2020", periods=3, freq="H").to_series() diff --git a/tests/test_models.py b/tests/test_models.py index f5439f48b..070b5b786 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -68,8 +68,12 @@ def test_infeasible_model(): solph.processing.meta_results(m) -@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") -@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") +@pytest.mark.filterwarnings( + "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" +) +@pytest.mark.filterwarnings( + "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" +) def test_multi_period_default_discount_rate(): """Test error being thrown for default multi-period discount rate""" timeindex = pd.date_range(start="2017-01-01", periods=100, freq="D") diff --git a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py index 92000187b..54fb46fda 100644 --- a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py +++ b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py @@ -26,8 +26,12 @@ from oemof.solph import views -@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") -@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") +@pytest.mark.filterwarnings( + "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" +) +@pytest.mark.filterwarnings( + "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" +) def test_multi_period_dispatch_model(solver="cbc"): """Test a simple multi_period dispatch model""" diff --git a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py index 42172ceaf..1bce009a0 100644 --- a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py +++ b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py @@ -27,8 +27,12 @@ from oemof.solph import views -@pytest.mark.filterwarnings("ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning") -@pytest.mark.filterwarnings("ignore:CAUTION! You specified the 'periods' attribute:UserWarning") +@pytest.mark.filterwarnings( + "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" +) +@pytest.mark.filterwarnings( + "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" +) def test_multi_period_investment_model(solver="cbc"): """Test a simple multi_period investment model for multiple SinkDSM approaches""" From 91b2a500ab7f92929bb88aa223ee9cd783803675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:13:28 +0100 Subject: [PATCH 165/180] Add line breaks to long strings --- tests/multi_period_constraint_tests.py | 6 ++++-- tests/test_energy_system.py | 6 ++++-- tests/test_models.py | 3 ++- .../test_multi_period_dispatch_model.py | 3 ++- .../test_multi_period_investment_model.py | 3 ++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/multi_period_constraint_tests.py b/tests/multi_period_constraint_tests.py index dfd483e77..417fdf0dd 100644 --- a/tests/multi_period_constraint_tests.py +++ b/tests/multi_period_constraint_tests.py @@ -24,7 +24,8 @@ # Warnings about the fature being experimental: @pytest.mark.filterwarnings( - "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" + "ignore:Ensure that your timeindex and timeincrement are" + " consistent.:UserWarning" ) @pytest.mark.filterwarnings( "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" @@ -34,7 +35,8 @@ "ignore:You did not specify an interest rate.:UserWarning" ) @pytest.mark.filterwarnings( - "ignore:By default, a discount_rate of 0.02 is used for a multi-period model.:UserWarning" + "ignore:By default, a discount_rate of 0.02 is used for a multi-period" + " model.:UserWarning" ) class TestsMultiPeriodConstraint: @classmethod diff --git a/tests/test_energy_system.py b/tests/test_energy_system.py index a4012f91f..d4a9b0cf4 100644 --- a/tests/test_energy_system.py +++ b/tests/test_energy_system.py @@ -14,7 +14,8 @@ @pytest.mark.filterwarnings( - "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" + "ignore:Ensure that your timeindex and timeincrement are" + " consistent.:UserWarning" ) @pytest.mark.filterwarnings( "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" @@ -39,7 +40,8 @@ def test_add_periods(): @pytest.mark.filterwarnings( - "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" + "ignore:Ensure that your timeindex and timeincrement are" + " consistent.:UserWarning" ) @pytest.mark.filterwarnings( "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" diff --git a/tests/test_models.py b/tests/test_models.py index 070b5b786..b7e7eda8f 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -69,7 +69,8 @@ def test_infeasible_model(): @pytest.mark.filterwarnings( - "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" + "ignore:Ensure that your timeindex and timeincrement are" + " consistent.:UserWarning" ) @pytest.mark.filterwarnings( "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" diff --git a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py index 54fb46fda..9b1ceef27 100644 --- a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py +++ b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_dispatch_model.py @@ -27,7 +27,8 @@ @pytest.mark.filterwarnings( - "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" + "ignore:Ensure that your timeindex and timeincrement are" + " consistent.:UserWarning" ) @pytest.mark.filterwarnings( "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" diff --git a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py index 1bce009a0..e8d36f7ce 100644 --- a/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py +++ b/tests/test_scripts/test_solph/test_multi_period_model/test_multi_period_investment_model.py @@ -28,7 +28,8 @@ @pytest.mark.filterwarnings( - "ignore:Ensure that your timeindex and timeincrement are consistent.:UserWarning" + "ignore:Ensure that your timeindex and timeincrement are" + " consistent.:UserWarning" ) @pytest.mark.filterwarnings( "ignore:CAUTION! You specified the 'periods' attribute:UserWarning" From ea7c62b918105e448ff3f70d0f6d1fd32dcc354e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:19:37 +0100 Subject: [PATCH 166/180] Add test for Storage investment arg warning --- tests/test_components.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/test_components.py b/tests/test_components.py index 9e71d4b13..f1db847b4 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -148,6 +148,17 @@ def test_generic_storage_with_convex_invest_offset(): ) +def test_generic_storage_invest_warning(): + with pytest.warns(FutureWarning): + bel = Bus() + components.GenericStorage( + label="storage7", + inputs={bel: Flow()}, + outputs={bel: Flow()}, + investment=Investment(), + ) + + def test_generic_storage_with_invest_and_fixed_losses_absolute(): """ Storage with fixed losses in the investment mode but no minimum or existing From 270594b8a6d78ebb35c8b05c05d3926e84c81815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:22:35 +0100 Subject: [PATCH 167/180] Add test for warnings when infer_last_interval is missing --- tests/test_time_index.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_time_index.py b/tests/test_time_index.py index db4049a1b..bbd388e75 100644 --- a/tests/test_time_index.py +++ b/tests/test_time_index.py @@ -29,6 +29,12 @@ def test_energysystem_with_datetimeindex(): assert es.timeincrement.sum() == 23 +def test_energysystem_with_datetimeindex(): + datetimeindex = pd.date_range("1/1/2012", periods=24, freq="H") + with pytest.warns(FutureWarning): + _ = solph.EnergySystem(timeindex=datetimeindex) + + def test_energysystem_with_datetimeindex_non_equidistant_infer_last_interval(): """Test EnergySystem with DatetimeIndex (non-equidistant)""" dtindex1 = pd.date_range("1/1/2012", periods=24, freq="H") From 6633b5a795e212f25df6c9f609e213dfb5eeec50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:27:58 +0100 Subject: [PATCH 168/180] Fix doubled name of test function --- tests/test_time_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_time_index.py b/tests/test_time_index.py index bbd388e75..f5a7aaf03 100644 --- a/tests/test_time_index.py +++ b/tests/test_time_index.py @@ -29,7 +29,7 @@ def test_energysystem_with_datetimeindex(): assert es.timeincrement.sum() == 23 -def test_energysystem_with_datetimeindex(): +def test_energysystem_interval_inference_warning(): datetimeindex = pd.date_range("1/1/2012", periods=24, freq="H") with pytest.warns(FutureWarning): _ = solph.EnergySystem(timeindex=datetimeindex) From 424f9097ffbeaf69566af506b5c842074e2468f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:35:32 +0100 Subject: [PATCH 169/180] Remove cookiecutterrc from MANIFEST The file is no longer present. --- MANIFEST.in | 1 - 1 file changed, 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index c80f59439..69992fa42 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,7 +5,6 @@ graft tests include .bumpversion.cfg include .coveragerc -include .cookiecutterrc include .editorconfig include AUTHORS.rst From 2fa8c13ab7627e94ed22db5fa0d3eab8be42ef5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 22 Dec 2023 12:36:04 +0100 Subject: [PATCH 170/180] Use standard compilant formating of version --- .bumpversion.cfg | 2 +- VERSION | 2 +- docs/conf.py | 2 +- setup.py | 2 +- src/oemof/solph/__init__.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 955f328cd..18fdcbc20 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.5.2dev2 +current_version = 0.5.2.dev2 commit = True tag = True diff --git a/VERSION b/VERSION index ae000fe0a..28bcfa005 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -__version__ = "0.5.2dev2" +__version__ = "0.5.2.dev2" diff --git a/docs/conf.py b/docs/conf.py index 6a7d75dea..d1adcfd5f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,7 @@ def setup(app): year = "2014-2023" author = "oemof-developer-group" copyright = "{0}, {1}".format(year, author) -version = release = "0.5.2dev2" +version = release = "0.5.2.dev2" pygments_style = "trac" templates_path = ["."] diff --git a/setup.py b/setup.py index 818f2ea0c..ac89066f9 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ def read(*names, **kwargs): setup( name="oemof.solph", - version="0.5.2dev2", + version="0.5.2.dev2", license="MIT", description=( "A model generator for energy system modelling and optimisation." diff --git a/src/oemof/solph/__init__.py b/src/oemof/solph/__init__.py index d8632f71c..c002c1b8e 100644 --- a/src/oemof/solph/__init__.py +++ b/src/oemof/solph/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.5.2dev2" +__version__ = "0.5.2.dev2" from . import buses from . import components From 6c2ab5823125c0728cd4c53d383f1e34c3881173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 10:58:23 +0100 Subject: [PATCH 171/180] Delete LOPF example The example (for an experimental feature) is no longer working. Also, it adds Edges (ElectricalLine) directly to the model which is against the style. --- docs/examples/electrical.lopf.rst | 7 - docs/examples/index.rst | 1 - examples/electrical/lopf.py | 227 ------------------------------ 3 files changed, 235 deletions(-) delete mode 100644 docs/examples/electrical.lopf.rst delete mode 100644 examples/electrical/lopf.py diff --git a/docs/examples/electrical.lopf.rst b/docs/examples/electrical.lopf.rst deleted file mode 100644 index 391f372e7..000000000 --- a/docs/examples/electrical.lopf.rst +++ /dev/null @@ -1,7 +0,0 @@ -Linear optimal power flow (lopf) --------------------------------- - -Three-Bus system -~~~~~~~~~~~~~~~~ - -.. automodule:: electrical.lopf diff --git a/docs/examples/index.rst b/docs/examples/index.rst index db44d467b..d5c4c6813 100644 --- a/docs/examples/index.rst +++ b/docs/examples/index.rst @@ -29,5 +29,4 @@ Examples minimal_investment.rst invest_nonconvex.rst offset_converter.rst - electrical.lopf.rst custom_constraints.rst diff --git a/examples/electrical/lopf.py b/examples/electrical/lopf.py deleted file mode 100644 index b8ab5d210..000000000 --- a/examples/electrical/lopf.py +++ /dev/null @@ -1,227 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -General description -------------------- -This script shows how to do a linear optimal powerflow (lopf) calculation -based on custom oemof components. The example is based on the PyPSA -simple lopf example. - -Note: As oemof currently does not support models with one timesteps, therefore -there are two. - -Code ----- -Download source code: :download:`lopf.py ` - -.. dropdown:: Click to display code - - .. literalinclude:: /../examples/electrical/lopf.py - :language: python - :lines: 44-221 - -Installation requirements -------------------------- -This example requires oemof.solph (v0.5.x), install by: - -.. code:: bash - - pip install oemof.solph[examples] - -To draw the graph pygraphviz is required, installed by: - -.. code:: bash - - pip install pygraphviz - -License -------- -Simon Hilpert - 12.12.2017 - simon.hilpert@uni-flensburg.de - -`MIT license `_ - -""" -import networkx as nx -import pandas as pd -from matplotlib import pyplot as plt -from oemof.network.graph import create_nx_graph - -from oemof.solph import EnergySystem -from oemof.solph import Investment -from oemof.solph import Model -from oemof.solph import processing -from oemof.solph import views -from oemof.solph.buses.experimental import ElectricalBus -from oemof.solph.components import Sink -from oemof.solph.components import Source -from oemof.solph.flows import Flow -from oemof.solph.flows.experimental import ElectricalLine - -try: - import pygraphviz as pygz -except ModuleNotFoundError: - pygz = None - - -def draw_graph( - grph, - edge_labels=True, - node_color="#AFAFAF", - edge_color="#CFCFCF", - plot=True, - node_size=2000, - with_labels=True, - arrows=True, - layout="neato", -): - """ - Draw a graph. This function will be removed in future versions. - - Parameters - ---------- - grph : networkxGraph - A graph to draw. - edge_labels : boolean - Use nominal values of flow as edge label - node_color : dict or string - Hex color code oder matplotlib color for each node. If string, all - colors are the same. - - edge_color : string - Hex color code oder matplotlib color for edge color. - - plot : boolean - Show matplotlib plot. - - node_size : integer - Size of nodes. - - with_labels : boolean - Draw node labels. - - arrows : boolean - Draw arrows on directed edges. Works only if an optimization_model has - been passed. - layout : string - networkx graph layout, one of: neato, dot, twopi, circo, fdp, sfdp. - """ - if isinstance(node_color, dict): - node_color = [node_color.get(g, "#AFAFAF") for g in grph.nodes()] - - # set drawing options - options = { - # "prog": "dot", - "with_labels": with_labels, - "node_color": node_color, - "edge_color": edge_color, - "node_size": node_size, - "arrows": arrows, - } - - # draw graph - pos = nx.drawing.nx_agraph.graphviz_layout(grph, prog=layout) - - nx.draw(grph, pos=pos, **options) - - # add edge labels for all edges - if edge_labels is True and plt: - labels = nx.get_edge_attributes(grph, "weight") - nx.draw_networkx_edge_labels(grph, pos=pos, edge_labels=labels) - - # show output - if plot is True: - plt.show() - - -def main(): - datetimeindex = pd.date_range("1/1/2017", periods=2, freq="H") - - es = EnergySystem(timeindex=datetimeindex) - - b_el0 = ElectricalBus(label="b_0", v_min=-1, v_max=1) - - b_el1 = ElectricalBus(label="b_1", v_min=-1, v_max=1) - - b_el2 = ElectricalBus(label="b_2", v_min=-1, v_max=1) - - es.add(b_el0, b_el1, b_el2) - - es.add( - ElectricalLine( - input=b_el0, - output=b_el1, - reactance=0.0001, - nominal_value=Investment(ep_costs=10), - min=-1, - max=1, - ) - ) - - es.add( - ElectricalLine( - input=b_el1, - output=b_el2, - reactance=0.0001, - nominal_value=60, - min=-1, - max=1, - ) - ) - - es.add( - ElectricalLine( - input=b_el2, - output=b_el0, - reactance=0.0001, - nominal_value=60, - min=-1, - max=1, - ) - ) - - es.add( - Source( - label="gen_0", - outputs={b_el0: Flow(nominal_value=100, variable_costs=50)}, - ) - ) - - es.add( - Source( - label="gen_1", - outputs={b_el1: Flow(nominal_value=100, variable_costs=25)}, - ) - ) - - es.add( - Sink(label="load", inputs={b_el2: Flow(nominal_value=100, fix=[1, 1])}) - ) - - m = Model(energysystem=es) - - # m.write('lopf.lp', io_options={'symbolic_solver_labels': True}) - - m.solve(solver="cbc", solve_kwargs={"tee": True, "keepfiles": False}) - - m.results() - - graph = create_nx_graph(es) - - if pygz is not None: - draw_graph( - graph, - plot=True, - layout="neato", - node_size=3000, - node_color={"b_0": "#cd3333", "b_1": "#7EC0EE", "b_2": "#eeac7e"}, - ) - - results = processing.results(m) - - print(views.node(results, "gen_0")["sequences"]) - print(views.node(results, "gen_1")["sequences"]) - print(views.node(results, "load")["sequences"]) - - -if __name__ == "__main__": - main() From c5cccdb7eeb23ccc2a527b302599ce1861168468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 11:26:56 +0100 Subject: [PATCH 172/180] Adapt to new Pyomo style in LP file --- tests/lp_files/dsm_module_oemof_extended.lp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lp_files/dsm_module_oemof_extended.lp b/tests/lp_files/dsm_module_oemof_extended.lp index 3ebe9b458..7d2eda425 100644 --- a/tests/lp_files/dsm_module_oemof_extended.lp +++ b/tests/lp_files/dsm_module_oemof_extended.lp @@ -79,7 +79,7 @@ c_e_SinkDSMOemofBlock_dsm_sum_constraint(demand_dsm_0)_: +0.99 SinkDSMOemofBlock_dsm_up(demand_dsm_0) +0.99 SinkDSMOemofBlock_dsm_up(demand_dsm_1) -1 SinkDSMOemofBlock_dsm_do_shift(demand_dsm_1) -= 0.0 += 0 bounds 0 <= SinkDSMOemofBlock_dsm_do_shift(demand_dsm_0) <= +inf From ca764e8e38153ff271edb583d7a25c68840e39d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 12:54:43 +0100 Subject: [PATCH 173/180] Do not set label in Converter This shoud be done at the Node. --- src/oemof/solph/components/_converter.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/oemof/solph/components/_converter.py b/src/oemof/solph/components/_converter.py index a2e9a559b..e32f86381 100644 --- a/src/oemof/solph/components/_converter.py +++ b/src/oemof/solph/components/_converter.py @@ -101,8 +101,6 @@ def __init__( conversion_factors=None, custom_attributes=None, ): - self.label = label - if inputs is None: warn_if_missing_attribute(self, "inputs") inputs = {} From ac81568f4a339ac3f86d8610515ae76741359894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 13:03:17 +0100 Subject: [PATCH 174/180] Revert "Merge pull request #1012 from oemof/fix/offset_converter_y-intercept" This reverts commit 72bfb3bddd4ca115d1ba82c2fa14e53cea9c80c9, reversing changes made to 7c7ba3be6a18a9187cbd53feb53e6630f0d2c80d. --- src/oemof/solph/components/_offset_converter.py | 8 ++++++-- tests/lp_files/offsetconverter.lp | 12 ++++++------ tests/lp_files/offsetconverter_multi_period.lp | 12 ++++++------ tests/lp_files/offsetconverter_nonconvex.lp | 6 +++--- .../lp_files/offsetconverter_nonconvex_investment.lp | 6 +++--- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/oemof/solph/components/_offset_converter.py b/src/oemof/solph/components/_offset_converter.py index 8369d8ded..606b0f3ad 100644 --- a/src/oemof/solph/components/_offset_converter.py +++ b/src/oemof/solph/components/_offset_converter.py @@ -245,7 +245,9 @@ def _relation_rule(block): # `NonConvexFlow`. try: expr += ( - m.InvestNonConvexFlowBlock.status[n, o, t] + m.InvestNonConvexFlowBlock.status_nominal[ + n, o, t + ] * n.coefficients[0][t] ) # `KeyError` occurs when more than one @@ -260,7 +262,9 @@ def _relation_rule(block): # (inside the `try` block) does not exist. except (KeyError, AttributeError): expr += ( - m.NonConvexFlowBlock.status[n, o, t] + m.NonConvexFlowBlock.status_nominal[ + n, o, t + ] * n.coefficients[0][t] ) block.relation.add((n, i, o, p, t), (expr == 0)) diff --git a/tests/lp_files/offsetconverter.lp b/tests/lp_files/offsetconverter.lp index a241b80fd..59b7c425e 100644 --- a/tests/lp_files/offsetconverter.lp +++ b/tests/lp_files/offsetconverter.lp @@ -47,32 +47,32 @@ c_e_NonConvexFlowBlock_status_nominal_constraint(gasBus_gasboiler_2)_: c_u_NonConvexFlowBlock_min(gasBus_gasboiler_0_0)_: -1 flow(gasBus_gasboiler_0_0) -+0.32 NonConvexFlowBlock_status(gasBus_gasboiler_0) ++0.32 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_0) <= 0 c_u_NonConvexFlowBlock_min(gasBus_gasboiler_0_1)_: -1 flow(gasBus_gasboiler_0_1) -+0.32 NonConvexFlowBlock_status(gasBus_gasboiler_1) ++0.32 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_1) <= 0 c_u_NonConvexFlowBlock_min(gasBus_gasboiler_0_2)_: -1 flow(gasBus_gasboiler_0_2) -+0.32 NonConvexFlowBlock_status(gasBus_gasboiler_2) ++0.32 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_2) <= 0 c_u_NonConvexFlowBlock_max(gasBus_gasboiler_0_0)_: +1 flow(gasBus_gasboiler_0_0) --1 NonConvexFlowBlock_status(gasBus_gasboiler_0) +-1 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_0) <= 0 c_u_NonConvexFlowBlock_max(gasBus_gasboiler_0_1)_: +1 flow(gasBus_gasboiler_0_1) --1 NonConvexFlowBlock_status(gasBus_gasboiler_1) +-1 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_1) <= 0 c_u_NonConvexFlowBlock_max(gasBus_gasboiler_0_2)_: +1 flow(gasBus_gasboiler_0_2) --1 NonConvexFlowBlock_status(gasBus_gasboiler_2) +-1 NonConvexFlowBlock_status_nominal(gasBus_gasboiler_2) <= 0 c_e_OffsetConverterBlock_relation(gasboiler_0_0)_: diff --git a/tests/lp_files/offsetconverter_multi_period.lp b/tests/lp_files/offsetconverter_multi_period.lp index fd0789adc..2f29944f2 100644 --- a/tests/lp_files/offsetconverter_multi_period.lp +++ b/tests/lp_files/offsetconverter_multi_period.lp @@ -147,37 +147,37 @@ c_u_NonConvexFlowBlock_max(gasboiler_thermalBus_2_5)_: c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_0_0)_: +0.9 flow(gasBus_gasboiler_0_0) -1 flow(gasboiler_thermalBus_0_0) --17 NonConvexFlowBlock_status(gasboiler_thermalBus_0) +-17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_0) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_0_1)_: +0.9 flow(gasBus_gasboiler_0_1) -1 flow(gasboiler_thermalBus_0_1) --17 NonConvexFlowBlock_status(gasboiler_thermalBus_1) +-17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_1) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_1_2)_: +0.9 flow(gasBus_gasboiler_1_2) -1 flow(gasboiler_thermalBus_1_2) --17 NonConvexFlowBlock_status(gasboiler_thermalBus_2) +-17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_2) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_1_3)_: +0.9 flow(gasBus_gasboiler_1_3) -1 flow(gasboiler_thermalBus_1_3) --17 NonConvexFlowBlock_status(gasboiler_thermalBus_3) +-17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_3) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_2_4)_: +0.9 flow(gasBus_gasboiler_2_4) -1 flow(gasboiler_thermalBus_2_4) --17 NonConvexFlowBlock_status(gasboiler_thermalBus_4) +-17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_4) = 0 c_e_OffsetConverterBlock_relation(gasboiler_gasBus_thermalBus_2_5)_: +0.9 flow(gasBus_gasboiler_2_5) -1 flow(gasboiler_thermalBus_2_5) --17 NonConvexFlowBlock_status(gasboiler_thermalBus_5) +-17 NonConvexFlowBlock_status_nominal(gasboiler_thermalBus_5) = 0 bounds diff --git a/tests/lp_files/offsetconverter_nonconvex.lp b/tests/lp_files/offsetconverter_nonconvex.lp index d05b85060..98ff1f1c0 100644 --- a/tests/lp_files/offsetconverter_nonconvex.lp +++ b/tests/lp_files/offsetconverter_nonconvex.lp @@ -78,19 +78,19 @@ c_u_NonConvexFlowBlock_max(diesel_genset_bus_electricity_0_2)_: c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_0)_: +0.5 flow(bus_diesel_diesel_genset_0_0) -1 flow(diesel_genset_bus_electricity_0_0) -+2.5 NonConvexFlowBlock_status(diesel_genset_bus_electricity_0) ++2.5 NonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_0) = 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_1)_: +0.5 flow(bus_diesel_diesel_genset_0_1) -1 flow(diesel_genset_bus_electricity_0_1) -+2.5 NonConvexFlowBlock_status(diesel_genset_bus_electricity_1) ++2.5 NonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_1) = 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_2)_: +0.5 flow(bus_diesel_diesel_genset_0_2) -1 flow(diesel_genset_bus_electricity_0_2) -+2.5 NonConvexFlowBlock_status(diesel_genset_bus_electricity_2) ++2.5 NonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_2) = 0 bounds diff --git a/tests/lp_files/offsetconverter_nonconvex_investment.lp b/tests/lp_files/offsetconverter_nonconvex_investment.lp index aa845ed66..4b9755dd5 100644 --- a/tests/lp_files/offsetconverter_nonconvex_investment.lp +++ b/tests/lp_files/offsetconverter_nonconvex_investment.lp @@ -119,19 +119,19 @@ c_u_InvestNonConvexFlowBlock_invest_nc_three(diesel_genset_bus_electricity_0_2)_ c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_0)_: +0.5 flow(bus_diesel_diesel_genset_0_0) -1 flow(diesel_genset_bus_electricity_0_0) -+2.5 InvestNonConvexFlowBlock_status(diesel_genset_bus_electricity_0) ++2.5 InvestNonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_0) = 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_1)_: +0.5 flow(bus_diesel_diesel_genset_0_1) -1 flow(diesel_genset_bus_electricity_0_1) -+2.5 InvestNonConvexFlowBlock_status(diesel_genset_bus_electricity_1) ++2.5 InvestNonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_1) = 0 c_e_OffsetConverterBlock_relation(diesel_genset_bus_diesel_bus_electricity_0_2)_: +0.5 flow(bus_diesel_diesel_genset_0_2) -1 flow(diesel_genset_bus_electricity_0_2) -+2.5 InvestNonConvexFlowBlock_status(diesel_genset_bus_electricity_2) ++2.5 InvestNonConvexFlowBlock_status_nominal(diesel_genset_bus_electricity_2) = 0 bounds From 3686b82b8343e7e186ed28aa9402d8ce1326f2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 13:31:17 +0100 Subject: [PATCH 175/180] Use explicit kwargs for Bus This seems to have been forgotten before. --- src/oemof/solph/buses/_bus.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/oemof/solph/buses/_bus.py b/src/oemof/solph/buses/_bus.py index 20f97ecaa..327a84728 100644 --- a/src/oemof/solph/buses/_bus.py +++ b/src/oemof/solph/buses/_bus.py @@ -40,9 +40,22 @@ class Bus(Node): """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.balanced = kwargs.get("balanced", True) + def __init__( + self, + label=None, + *, + balanced=True, + inputs=None, + outputs=None, + custom_properties=None, + ): + super().__init__( + label=label, + inputs=inputs, + outputs=outputs, + custom_properties=custom_properties, + ) + self.balanced = balanced def constraint_group(self): if self.balanced: From ef3df6ddd6c548d900d3724c417ed0e8beed28a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 14:27:34 +0100 Subject: [PATCH 176/180] Fix gradient example to work with explicit API --- examples/gradient_example/gradient_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gradient_example/gradient_example.py b/examples/gradient_example/gradient_example.py index 5df0d5ecb..ded553bbe 100644 --- a/examples/gradient_example/gradient_example.py +++ b/examples/gradient_example/gradient_example.py @@ -52,7 +52,7 @@ def main(): date_time_index = pd.date_range("1/1/2012", periods=48, freq="H") print(date_time_index) - energysystem = EnergySystem(timeindex=date_time_index, timemode="explicit") + energysystem = EnergySystem(timeindex=date_time_index, infer_last_interval=True) demand = [ 209643, From da50114a601bf62e892fd6c60c888ddde9cd17db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 14:27:46 +0100 Subject: [PATCH 177/180] Fix cellular example to work with explicit API --- examples/cellular/cellular.py | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/examples/cellular/cellular.py b/examples/cellular/cellular.py index 2d208a16e..633795aae 100644 --- a/examples/cellular/cellular.py +++ b/examples/cellular/cellular.py @@ -65,27 +65,13 @@ def main(): mysolver = "cbc" # create the energy cells - es = EnergySystem( - label="es", timeindex=daterange, infer_last_interval=False - ) - ec_1 = EnergySystem( - label="ec1", timeindex=daterange, infer_last_interval=False - ) - ec_2 = EnergySystem( - label="ec2", timeindex=daterange, infer_last_interval=False - ) - ec_1_1 = EnergySystem( - label="ec1_1", timeindex=daterange, infer_last_interval=False - ) - ec_1_2 = EnergySystem( - label="ec1_2", timeindex=daterange, infer_last_interval=False - ) - ec_2_1 = EnergySystem( - label="ec2_1", timeindex=daterange, infer_last_interval=False - ) - ec_2_2 = EnergySystem( - label="ec2_2", timeindex=daterange, infer_last_interval=False - ) + es = EnergySystem(timeindex=daterange, infer_last_interval=False) + ec_1 = EnergySystem(timeindex=daterange, infer_last_interval=False) + ec_2 = EnergySystem(timeindex=daterange, infer_last_interval=False) + ec_1_1 = EnergySystem(timeindex=daterange, infer_last_interval=False) + ec_1_2 = EnergySystem(timeindex=daterange, infer_last_interval=False) + ec_2_1 = EnergySystem(timeindex=daterange, infer_last_interval=False) + ec_2_2 = EnergySystem(timeindex=daterange, infer_last_interval=False) demand_1 = [10] * n_periods demand_2 = [10] * n_periods From 8962fefd7f0c55b993cf7ab159a9e8aa8deda432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 14:41:16 +0100 Subject: [PATCH 178/180] Fix include of cellular example in docs --- examples/cellular/cellular.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cellular/cellular.py b/examples/cellular/cellular.py index 633795aae..e82df3b2d 100644 --- a/examples/cellular/cellular.py +++ b/examples/cellular/cellular.py @@ -21,7 +21,7 @@ .. literalinclude:: /../examples/cellular/cellular.py :language: python - :lines: 45-346 + :lines: 45- Installation requirements ------------------------- From 306a788bab56784d0343699baf68c24e3cf37dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 14:43:06 +0100 Subject: [PATCH 179/180] Adhere to Black style --- examples/gradient_example/gradient_example.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/gradient_example/gradient_example.py b/examples/gradient_example/gradient_example.py index ded553bbe..c1e153668 100644 --- a/examples/gradient_example/gradient_example.py +++ b/examples/gradient_example/gradient_example.py @@ -52,7 +52,9 @@ def main(): date_time_index = pd.date_range("1/1/2012", periods=48, freq="H") print(date_time_index) - energysystem = EnergySystem(timeindex=date_time_index, infer_last_interval=True) + energysystem = EnergySystem( + timeindex=date_time_index, infer_last_interval=True + ) demand = [ 209643, From 93b1b1f4961743873d78e08c541713e819619c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 12 Jan 2024 14:47:03 +0100 Subject: [PATCH 180/180] Release version v0.5.2 --- .bumpversion.cfg | 2 +- VERSION | 2 +- docs/conf.py | 2 +- docs/whatsnew/v0-5-2.rst | 14 +++++++++----- .../offset_diesel_genset_nonconvex_investment.py | 1 - setup.py | 2 +- src/oemof/solph/__init__.py | 2 +- 7 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 18fdcbc20..a7c7463da 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.5.2.dev2 +current_version = 0.5.2 commit = True tag = True diff --git a/VERSION b/VERSION index 28bcfa005..722515271 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -__version__ = "0.5.2.dev2" +__version__ = "0.5.2" diff --git a/docs/conf.py b/docs/conf.py index d1adcfd5f..3084c8419 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,7 @@ def setup(app): year = "2014-2023" author = "oemof-developer-group" copyright = "{0}, {1}".format(year, author) -version = release = "0.5.2.dev2" +version = release = "0.5.2" pygments_style = "trac" templates_path = ["."] diff --git a/docs/whatsnew/v0-5-2.rst b/docs/whatsnew/v0-5-2.rst index 7644d1aa6..119e6ddaa 100644 --- a/docs/whatsnew/v0-5-2.rst +++ b/docs/whatsnew/v0-5-2.rst @@ -1,10 +1,11 @@ -v0.5.2 (????) -------------- +v0.5.2 (January 12th, 2024) +--------------------------- API changes ########### * New bool attribute `use_remaining_value` of `oemof.solph.EnergySystem` +* Use list for period definition in multi-period investment optimization. New features ############ @@ -27,14 +28,17 @@ Bug fixes * Fix minimum uptime being relevant for initial downtime (and vice versa). * Fix duplicated discounting of fixed costs for multi-period investment -Testing -####### - Other changes ############# * Improved compatibility with upcoming oemof.network +Known issues +############ + +* Documentation, example and API of OffsetConverter are inconsistent + and might not work as expected. + Contributors ############ diff --git a/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py b/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py index 38d2874c3..941517ec2 100644 --- a/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py +++ b/examples/offset_converter_example/offset_diesel_genset_nonconvex_investment.py @@ -596,7 +596,6 @@ def offset_converter_example(): ax.set_xlabel("diesel genset load [%]") ax.set_xlim(min_load * 100 - 5, max_load * 100 + 5) - ax.set_ylim(min_efficiency * 100 - 2, max_efficiency * 100 + 2) plt.show() diff --git a/setup.py b/setup.py index ac89066f9..e681d5d27 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ def read(*names, **kwargs): setup( name="oemof.solph", - version="0.5.2.dev2", + version="0.5.2", license="MIT", description=( "A model generator for energy system modelling and optimisation." diff --git a/src/oemof/solph/__init__.py b/src/oemof/solph/__init__.py index c002c1b8e..aec05bae4 100644 --- a/src/oemof/solph/__init__.py +++ b/src/oemof/solph/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.5.2.dev2" +__version__ = "0.5.2" from . import buses from . import components