Giter Site home page Giter Site logo

oemof / oemof-solph Goto Github PK

View Code? Open in Web Editor NEW
281.0 39.0 121.0 36.82 MB

A model generator for energy system modelling and optimisation (LP/MILP).

Home Page: https://oemof.org

License: MIT License

Python 99.92% Batchfile 0.08%
energy energy-system modelling modelling-framework

oemof-solph's Introduction

tox-pytest tox-checks AppVeyor Build Status Coverage Status Coverage Status

Scrutinizer Status Codacy Code Quality Status CodeClimate Quality Status

PyPI Wheel packaging Supported versions

Documentation Status Zenodo DOI

PyPI Package latest release Commits since latest release



oemof.solph

A model generator for energy system modelling and optimisation (LP/MILP)

Introduction

The oemof.solph package is part of the Open energy modelling framework (oemof). This is an organisational framework to bundle tools for energy (system) modelling. oemof-solph is a model generator for energy system modelling and optimisation.

The package oemof.solph is very often called just oemof. This is because installing the oemof meta package was once the best way to get oemof.solph. Notice that you should prefeably install oemof.solph instead of oemof if you want to use solph.

Everybody is welcome to use and/or develop oemof.solph. Read our contribution section.

Contribution is already possible on a low level by simply fixing typos in oemof's documentation or rephrasing sections which are unclear. If you want to support us that way please fork the oemof-solph repository to your own GitHub account and make changes as described in the github guidelines

If you have questions regarding the use of oemof including oemof.solph you can visit the openmod forum (tag oemof or tag oemof-solph) and open a new thread if your questions hasn't been already answered.

Keep in touch! - You can become a watcher at our github site, but this will bring you quite a few mails and might be more interesting for developers. If you just want to get the latest news, like when is the next oemof meeting, you can follow our news-blog at oemof.org.

Documentation

The oemof.solph documentation is powered by readthedocs. Use the project site of oemof.solph to choose the version of the documentation. Go to the download page to download different versions and formats (pdf, html, epub) of the documentation.

Installation

If you have a working Python installation, use pypi to install the latest version of oemof.solph. Python >= 3.8 is recommended. Lower versions may work but are not tested.

We highly recommend to use virtual environments. Please refer to the documentation of your Python distribution (e.g. Anaconda, Micromamba, or the version of Python that came with your Linux installation) to learn how to set up and use virtual environments.

(venv) pip install oemof.solph

If you want to use the latest features, you might want to install the developer version. The developer version is not recommended for productive use:

(venv) pip install https://github.com/oemof/oemof-solph/archive/dev.zip

For running an oemof-solph optimisation model, you need to install a solver. Following you will find guidelines for the installation process for different operating systems.

Installing a solver

There are several solvers that can work with oemof, both open source and commercial. Two open source solvers are widely used (CBC and GLPK), but oemof suggests CBC (Coin-or branch and cut). It may be useful to compare results of different solvers to see which performs best. Other commercial solvers, like Gurobi or Cplex, are also options. Have a look at the pyomo docs to learn about which solvers are supported.

Check the solver installation by executing the test_installation example below (see section Installation Test).

Linux

To install the solvers have a look at the package repository of your Linux distribution or search for precompiled packages. GLPK and CBC ares available at Debian, Feodora, Ubuntu and others.

Windows

  1. Download CBC
  2. Download GLPK (64/32 bit)
  3. Unpack CBC/GLPK to any folder (e.g. C:/Users/Somebody/my_programs)
  4. Add the path of the executable files of both solvers to the PATH variable using this tutorial
  5. Restart Windows

Check the solver installation by executing the test_installation example (see the Installation test section).

Mac OSX

Please follow the installation instructions on the respective homepages for details.

CBC-solver: https://projects.coin-or.org/Cbc

GLPK-solver: http://arnab-deka.com/posts/2010/02/installing-glpk-on-a-mac/

If you install the CBC solver via brew (highly recommended), it should work without additional configuration.

conda

Provided you are using a Linux or MacOS, the CBC-solver can also be installed in a conda environment. Please note, that it is highly recommended to use pip after conda, so:

(venv) conda install -c conda-forge coincbc
(venv) pip install oemof.solph

Installation test

Test the installation and the installed solver by running the installation test in your virtual environment:

(venv) oemof_installation_test

If the installation was successful, you will receive something like this:

*********
Solver installed with oemof:
glpk: working
cplex: not working
cbc: working
gurobi: not working
*********
oemof.solph successfully installed.

as an output.

Contributing

A warm welcome to all who want to join the developers and contribute to oemof.solph.

Information on the details and how to approach us can be found in the oemof documentation .

Citing

For explicitly citing solph, you might want to refer to DOI:10.1016/j.simpa.2020.100028, which gives an overview over the capabilities of solph. The core ideas of oemof as a whole are described in DOI:10.1016/j.esr.2018.07.001 (preprint at arXiv:1808.0807). To allow citing specific versions, we use the zenodo project to get a DOI for each version.

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.

You are welcome to contribute your own examples via a pull request or by e-mailing us (see here for contact information).

License

Copyright (c) oemof developer group

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

oemof-solph's People

Contributors

antonellaconsolinno avatar bachibouzouk avatar birgits avatar bmlancien avatar c-moeller avatar ckaldemeyer avatar dfuh avatar e-zolotarevskaya avatar fabiantu avatar franzipl avatar fwitte avatar gnn avatar gplssm avatar henhuy avatar jnnr avatar jokochems avatar joroeder avatar lensum avatar lmilletb avatar magering avatar nailend avatar nesnoj avatar p-snft avatar pkassing avatar sasa821 avatar simnh avatar srhbrnds avatar steffengit avatar tobirohrer avatar uvchik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oemof-solph's Issues

Abstract Base Class Attributes

We already had some discussions about the attributes and their meaning of the base-class objects.

At the moment we are using a mix of well known economic notations such as opex, capex etc.
and technical parameters that refer to the graph nature of out energysystem model (in_max, out_max, etc)

I talked to @gnn and @ckaldemeyer and if I got it right, it might be a good idea to have abstractly named attributes to be consitent with the general representation as a graph.

Starting with an example:
Replacing the attributes:

self.in_max = ..
self.out_max = ... 
self.in_min = ... 
self.out_min = .. 
self.add_out_limit = .. 

by bounds::

self.bounds = kwargs.get('bounds',
                                     {'inflow': [None, (None, None), None],
                                      'outflow': [None, (None, None), None]}

Additionally for economic parameters:

 self.costs = kwargs.get('costs', {'inflow':  None,
                                          'outflow': 0,
                                          'ramping': {'up': None,
                                                           'down': None},
                                          'startup': None,
                                          'shutdown': None,
                                          'capital': None,
                                          'fix' : 0,
                                          'wacc': 0.05})

With such a (or a similar) structure we could allow for very individuell modeling of the energysystems
without having a huge amount of different attributes. I think in a mid-term perpective we should
move in this direction, maybe it is a good idea to do so before all apps etc. are finished?

What do you think: @gnn @ckaldemeyer @uvchik @cswh @caro-rli ?

Check implementation of time-increment indepency

So far we are only calculating on an hourly basis which implies that power and energy have the same value e. g. 1 MW equals 1 MWh. This is also reflected in all underlying solph-equations which to not distinguish between power and energy.

To allow time-increment independency, all equations that contain energy balances have to be extended by a multiplication with the time-increment.

Example:

A (very) simple storage balance:

W_sto(t)= W_sto(t-1) + Tau * (P_sto_in(t) - P_sto_out(t)) for all t element [1, t_max]

In this case "Tau" is the chosen time-increment (e.g. 0.25 h).

Automatically register entities

Every Entity instance created should automatically be added to the entities attribute of an existing EnergySystem instance.
See also #19.

Simulation-object for solve-method of optimizationmodel not working from outside energysystem class

At the moment the simulation-object only works in combination with optimize method of the energy_system class. I should work as well from outside the energysystem if the solve method is called for the optimization model.

I added this (removed again) inside the sovle-method of OptimizationModel() in the solph package as an
idea:

        debug = kwargs.get('debug', self.energysystem.simulation.debug)
        duals = kwargs.get('duals', self.energysystem.simulation.duals)
        solver = kwargs.get('solver', self.energysystem.simulation.solver)
        solver_io = kwargs.get('solver_io',
                               self.energysystem.simulation.solver_io)

Which versions do we want to have at readthedocs (RTD)?

Do we get a decision until the next release? Would be great ๐Ÿ˜„

  1. Which branches do we want to show?
  2. What should be the default branch?

There is no fall-back at RTD. If somebody links to .../en/dev and this link doesn't exist anymore an error is shown. Therefore I think it is good to decide soon.

Beside the feature branches we can offer documentations for the following branches/labels:

I did not find a way to change the references of latest and stable!

name description
latest master-branch (edit: dev-branch)
stable last version label (now: v0.0.1, next week: v0.0.2)
v.0.0.1, v0.0.2, .... all versions we do release
dev dev-branch
master master-branch

Problem with objective function in storage example

I have taken a look at the objective function in the lp file which is generated when running the storage example (oemof_base/examples/storage_optimization). This looks very strange for me:

min
objective:
+50 w(pp_gas_bel_0)
+50 w(pp_gas_bel_1)
...
+50 w(pp_gas_bel_8760)
+28730000 ONE_VAR_CONSTANT

As far as I can see only opex_var (50) of the gas power plant and a constant variable is considered. What about the storage output? Why is this not part of the objective function?

Also invest variables are missing.

Does anyone know?

Should "results_to_objects" be the default post-processing?

At the moment it works like this:

my_energysystem.optimize()
pp.results_to_objects(my_energysystem.optimization_model)

Is it possible to write the results to the object by default and use an optional parameter to prevent it from doing so.

And if we write the results to the object, do we still need the 'optimization_model' attribute. Is it possible to remove it by an optional parameter or does it still holds essential informations?

I would like to dump the EnergySystem object with the results but it does not work if the 'optimization_model' attribute is still there.

Github issue filter for mentions group

Does anyone know how to filter the issues to show all issues where a group is mentioned?

  • mentions:cswh works
  • mentions:oemof/oemof-main does not work
    The function would make it much easier in my opinion to filter for relevant issues which need "urgent attention". If it does not work, we should have some better rules for the use of labels. So far there are no rules for labelling issues and everybody does it as he feels like?

Check example app

Check the scenario in example app and decide if another (or second) example is necessary.

Find a way for string representation of 'blocks' inside solph

At the moment solph uses blocks for every base class to group constraints and variables etc. Blocks are
attributes of the OptimizationModel() instance. Names of the attributes are set with the class name converted to a string.

This is very unhandy for debugging and model analysis (e.g. lp-files) and for calling these attributes as well as they can only be called with getattr(model, str(class)).

We should find a way to have a simple, stringent and short string representation for the blocks.

Storage model in investment mode: some understanding problems

Hi there,
even though I was involved in the development of the storage functionalities, I still have some problems in understanding.. I have an investment model with storage component and without any constraints concerning upper and lower bounds, so my storage component definition would look like this.. only buses, technical and economic parameters are given:

storage = transformer.Storage(uid='sto_simple',
                              inputs=[bel_hh],
                              outputs=[bel_hh],
                              eta_in=1,
                              eta_out=0.8,
                              cap_loss=0.00,
                              opex_fix=35,
                              opex_var=10e10,
                              capex=1000,
                              cap_initial=0,
                              c_rate_in=1/6,
                              c_rate_out=1/6)

I get this error:

  File "/home/caro/rlihome/Git/oemof_base/oemof/core/network/entities/components/transformers.py", line 170, in __init__
    'Did you specify c_rate_out and cap_max?')
ValueError: Failed to set out_max automatically.Did you specify c_rate_out and cap_max?

.., because I didn't specify cap_max, which is the maximum value of state of charge (as absolute value), means the storage capacity.

As far as I understand, cap_max is necessary here to calculate out_max (c_rate * cap_max), which is the maximum output value in every timestep and an attribute for every component. So I have to either define out_max or cap_max when creating my storage object. But since I have an investment model, those two attributes are variables in my case and I want to let the model calculate them.

I really don't get it :-(
What is my mistake here?

@simonhilpert
@ckaldemeyer

Renaming the code folder of oemof_base to avoid errors

@oemof/oemof-main : Shall we just rename the code folder to oemof_base?

The python convention is to name the code folder as the package name. @gnn said that it should also work with different named folders but right now it causes errors (see #44).

As long as nobody knows how to avoid these errors I vote for renaming the code folder to oemof_base.

I label it urgent because at the moment the example does not work if you install oemof using
pip3 install oemof_base.

sudo pip3 install oemof, import oemof not working

Tried to install oemof with "sudo pip3 install oemof". Everything seems to work fine, no errors, but import oemof in python got me a "no module named oemof" error. Downloading the zipped package and installing with "pip3 -e /path" worked fine, import oemof also. Do I have to adjust some environment variables when installing otherwise?

Allow entities to have non string uids

Using the Two-Region-Example with the actual commit (e87fd93) on the two_region_example branch, I get a pyomo-error. I do not know pyomo very good but I checked the entities and could not find anything. Everything seems to be like it was before.

Does anybody has an idea what cases this error?

INFO:root:Processing region: Landkreis Wittenberg (LanWit)
INFO:root:Processing region: Stadt Dessau-RoรŸlau (StaDes)
ERROR: Constructing component 'w_index_0' from data=None failed:
    ValueError: The value=('bus', 'Landkreis Wittenberg', 'elec', 'sink', 'Landkreis Wittenberg', 'elec') does not have dimension=2, which is needed for set=w_index_0
ERROR:pyomo.core:Constructing component 'w_index_0' from data=None failed:
ValueError: The value=('bus', 'Landkreis Wittenberg', 'elec', 'sink', 'Landkreis Wittenberg', 'elec') does not have dimension=2, which is needed for set=w_index_0
Traceback (most recent call last):
  File "/home/uwe/rli-lokal/git_home/oemof_base/examples/development_examples/two_regions_example.py", line 259, in <module>
    TwoRegExample.optimize()
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/core/energy_system.py", line 89, in optimize
    self.optimization_model = OM(energysystem=self)
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/solph/optimization_model.py", line 89, in __init__
    var.add_continuous(model=self, edges=self.all_edges)
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/solph/variables.py", line 79, in add_continuous
    model.w = po.Var(edges, model.timesteps, within=po.NonNegativeReals)
  File "/usr/local/lib/python3.4/dist-packages/pyomo/core/base/block.py", line 448, in __setattr__
    self.add_component(name, val)
  File "/usr/local/lib/python3.4/dist-packages/pyomo/core/base/block.py", line 686, in add_component
    self._add_temporary_set(val)
  File "/usr/local/lib/python3.4/dist-packages/pyomo/core/base/block.py", line 593, in _add_temporary_set
    val.cname()+"_index_"+str(ctr)
  File "/usr/local/lib/python3.4/dist-packages/pyomo/core/base/block.py", line 620, in _construct_temporary_set
    self.add_component(name,obj)
  File "/usr/local/lib/python3.4/dist-packages/pyomo/core/base/block.py", line 780, in add_component
    val.construct(data)
  File "/usr/local/lib/python3.4/dist-packages/pyomo/core/base/sets.py", line 1197, in construct
    self.add(val)
  File "/usr/local/lib/python3.4/dist-packages/pyomo/core/base/sets.py", line 746, in add
    self._verify(tmp)
  File "/usr/local/lib/python3.4/dist-packages/pyomo/core/base/sets.py", line 699, in _verify
    raise ValueError("The value="+str(element)+" does not have dimension="+str(self.dimen)+", which is needed for set="+self.cname(True))
ValueError: The value=('bus', 'Landkreis Wittenberg', 'elec', 'sink', 'Landkreis Wittenberg', 'elec') does not have dimension=2, which is needed for set=w_index_0

storage_invest example does not work for a fixed storage

If you switch the investment option to False the example raises an error.

- transformer.Storage.optimization_options.update({'investment': True})
+ transformer.Storage.optimization_options.update({'investment': False})

storage = transformer.Storage(uid='sto_simple',
                              inputs=[bel],
                              outputs=[bel],
                              eta_in=1,
                              eta_out=0.8,
                              cap_loss=0.00,
                              opex_fix=35,
                              opex_var=10e10,
                              capex=1000,
-                             cap_max=0,
+                             cap_max=1000,
                              cap_initial=0,
                              c_rate_in=1/6,
                              c_rate_out=1/6)
Traceback (most recent call last):
  File "/home/uwe/rli-lokal/git_home/oemof_base/examples/storage_optimization/storage_invest.py", line 155, in <module>
    energysystem.optimize()
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/core/energy_system.py", line 89, in optimize
    self.optimization_model = OM(energysystem=self)
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/solph/optimization_model.py", line 114, in __init__
    assembler.registry[cls](e=None, om=self, block=block)
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/solph/optimization_model.py", line 551, in _
    om.default_assembler(block)
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/solph/optimization_model.py", line 162, in default_assembler
    block.optimization_options[option](self, block)
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/solph/optimization_model.py", line 532, in linear_constraints
    var.set_bounds(om, block, side='output')
  File "/home/uwe/rli-lokal/git_home/oemof_base/oemof/solph/variables.py", line 144, in set_bounds
    model.w[e1, e2, t].setub(out_max[e1][0])
TypeError: 'NoneType' object is not subscriptable

Who will be additional owner of in oemof?

Decision wanted from: @oemof/oemof-main .

I think we should add owner with admin rights - e.g. for small changes in between and not only relying on two people.

Who wants to be owner and take some responsibilty for the group-page, as well as this repository on github? I propose @ckaldemeyer .

outputlib with pandas - Improvements

Some changes still have to be done. I am using this issue to collect and discuss ideas.

Ideas for changes:

  • It should be possible to pass a result-object directly. For this, we need a way to deal with the datetime-index which normally comes from the energy system
  • Add a flag like "return_df". If set to True, the dataframe-object will be returned directly
  • Add possibility to exclude components in plot_bus() method
  • Add a plot method that gives a good overview about the bus balance. My idea would be a stacked area or a normal stacked stackplot. All inputs are positive and all outputs negative. Additionally, the residual load will be plotted as a line and should be zero.
  • Add methods to store/restore the dataframe using pickle or something equivalent
  • Realize dataframe creation and plotting in different classes (separate data and visualisation)

Add mathematical descriptions/notations for solph

The mathematical description in solph is not 100 % in line. For this a static rst. file should be created. This file will contain general informations and notations for the mathematical description.

The following infos should be given in a structured(table-like) format:

variable names,
math. sets,
math. parameter

Docstrings in solph should be in line with these general informations.

outputlib - basic plots

Uwe has already started with his outputlib and created a method which creates a dataframe with all component timeseries arround a given bus.

He started with basic matplotlib which has all configuration options but in my opinion sometimes to many for standard plots as it is overwhelming...

After some trying my idea would be to go with the pandas basic plotting functions (based on matplotlib) for the basic plotting functions and the plots for renpass-gis.

Here's a small example with a handfull of plots and some possible configuration options beyond the standard functionalities (needs matplotlib >= 1.4):

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from datetime import datetime as dt
mpl.style.use('ggplot')

# Generate sample data
sample_data = np.random.rand(24*365, 5)
df = pd.DataFrame(sample_data,
                  index=pd.date_range('1/1/2015 00:00',
                                      periods=len(sample_data), freq='H'))

# Select date range to plot
date_from = dt(2015, 12, 22, 0, 0)
date_to = dt(2015, 12, 22, 23, 0)
df = df.loc[date_from:date_to]

# Plotting
# Formatting-tuple (title, colormap, xlabel, ...)
# for matplotlib.axes.AxesSubplot object could
# be passed by kwargs later
df.plot(kind='line', colormap='Spectral', title='Line Plot', linewidth='2')
[(ax.set_ylabel("Power in GW"),
 ax.set_xlabel("Date and Time"),
 ax.legend(('Wind', 'PV', 'Biomass', 'RoR', 'Demand'), loc='upper right'))
 for ax in plt.gcf().axes]

df.plot(kind='bar', stacked=True, colormap='Greens', title='Bar Plot')
[ax.legend(loc='upper right') for ax in plt.gcf().axes]

df.plot(kind='barh', stacked=True, colormap='Oranges', title='H-Bar Plot')
[ax.legend(loc='upper right') for ax in plt.gcf().axes]

df.plot(kind='area', stacked=False, alpha=0.5, colormap='Spectral',
        title='Area Plot')
[ax.legend(('Wind', 'PV', 'Biomass', 'RoR', 'Demand'),
           loc='upper right') for ax in plt.gcf().axes]

df.plot(kind='box', colormap='Reds', title='Box Plot')
[ax.legend(loc='upper right') for ax in plt.gcf().axes]

df.loc['2015-12-22 12:00:00':'2015-12-22 18:00:00', 2:3] \
    .plot(kind='hist', stacked=True, bins=20, colormap='ocean',
          title='Histogram of a subset')
[ax.legend(('Col1', 'Col2'), loc='upper right') for ax in plt.gcf().axes]

df.plot(kind='scatter', x=0, y=1,
        title='Scatter Plot (first vs. second column)')
[ax.legend(loc='upper right') for ax in plt.gcf().axes]

It would be quickly implemented on top of Uwes work and should fulfill most needs as I do not want to spend too much time on visualisation tweaking.

@oemof/oemof-main

Whats your opinion on this?

Happy christmas
Cord

The release of v0.0.2 is coming up soon

The deadline of the December release is the 22nd of December at 8 am.

  • Set the milestone to the next release if you will not be able to close your issue until the deadline of the December release.
  • Add all changes you made (fixes, enhancements,...) to the whatsnew-file and commit them. In the future every merge into the dev branch should contain a change of the whatsnew-file.
  • Merge everything you want to release into the dev branch until the deadline . Later merges/commits will be ignored. Close the related issue.

There should not be any open issue related to the December milestone on the morning of the 22.12.!

Implement rolling - optimization in solph

It makes sense to implement a rolling timehorizon for optimization problems in the solph module for two reasons:

  • more realistic results
  • reduction of memory usage for very large problems

Adding a method to dump/restore attributes from/to an EnergySystem instance

This features is very interesting for testing environments.

If you are fixing a bug in solph for example you can save the time creating the EnergySystem instance again and again.

my_energysystem = es.EnergySystem()
# [...] adding hundreds of entities, attributes and a simulation instance (takes 2 minutes)
my_energysystem.dump() 
my_energysystem.optimize()
# [...] do anything with the results

Within the bug-fix-process you can restore the dump:

my_energysystem = es.EnergySystem()
my_energysystem.restore()  # (takes less than 2 seconds)
my_energysystem.optimize()
# [...] do anything with the results

The dump/restore method creates a logging.debug message and(!) returns the message. So you can just use logging.info(my_energysystem.restore()) or print(my_energysystem.restore()) to get the message on the screen.

Do you think that it should not be a method of the EnergySystem class but a function of the "tools" sub-package? Feedback wanted!

Revise docstrings

State of existing docstrings

(1) no docstring
(2) insufficient docstring, wrong layout
(3) sufficient docstring but wrong layout
(4) seems okay

core/energy_system.py

  • EnergySystem (1)
  • EnergyRegion (1)
  • Simulation (1)

core/network/init.py

  • Entity (2)

core/network/entity/init.py

  • Bus (2)
  • Components (3)

core/network/entity/components/init.py

  • Sink (2)
  • Source (2)
  • Transformer (3)
  • Transport (2)

core/network/entity/components/source.py

  • FixedSource (2)
  • DispatchSource (2):
  • Commodity (2)

demandlib/demand.py

  • electrical_demand (5)
  • methods of electrical_demand (1-3)

Check, revise and ask for support if necessary.

Entity does not appear in the EnergySystem object

I created an EnergySystem object and than created a bus. This bus should automatically appear in the entities list of the EnergySystem but it does not.

Do I have to pass the EnergySystem to the entity?

So far it looks like this:

Bus(uid=('bus', 'global', 'coal'), type='coal', price=60, sum_out_limit=10e10)

Usage of Python/oemof-packages

I have just stumpled across an article about a Python workflow using Anaconda: http://stiglerdiet.com/blog/2015/Nov/24/my-python-environment-workflow-with-conda/ .

By the way, I got it from http://www.pythontips.com which is worth outchecking ;-)

So far we are a small crowd of developers mostly working on GNU/Linux and only have a few pure application-users. In the installation HowTo, everything is explained using the systems Python installation which can have some disadvatages when working on different projects, versions, etc.. See the article for more information.

Even if that might not apply for most of us, when I look at the future development and usage of oemof in university courses and seminars, I see long installation parties for different operating systems (Windows, OSX, Linux, ...) coming since the Python distributions, PATH-adjustments, etc. differ a lot among the OSes.

If I get the above article right, all this could be prevented by using the explained workflow since Anaconda is available for all mainstream operating systems. Looking at the license (which is BSD 3-clause: http://docs.continuum.io/anaconda/eula) we shouldn't get into trouble. If we did it like this, our installation HowTo would be comparably lean, similar to Stefan's: http://docs.callio.pe/en/stable/user/installation.html

@oemof/oemof-main What do you think?

Coding & Documentation: American or British English?

As Caro mentioned, another decision has to be made about the spelling. This is quite fundemental and should be written down in the documentation part "How to document?".

I vote for British English since we are mostly located in and focused on Europe and the openmod-initiative already also uses British English.

Titles oemof and oemof/oemof_base

Hello on github ;-)

Here's my first issue on the titles which I don't find suitable:

"Model of an energy supply system as open framework with modular structure." (oemof)

"open energy modelling framework - an open source model to optimise energy systems" (oemof/oemof_base)

For me oemof is not a model of one (or more) energy supply systems or a model to optimise energy systems but empowers the users to model (different parts) of energy supply systems and optionally provides the possibility to optimise them.

What do you think? I'll make up my mind meanwhile..

Change default repository

You discussed your git workflow on your release meeting and semi-decided in favor of the common git-flow. This flow changes the meaning of the master branch from a "main"-branch to a "latest-release"-branch that is relatively outdated. Yet, it is the first branch that you visit on your git-hub.

It might be useful if you change the default branch from master to develop.

Unique class names

At the moment I am working on a dataframe representation of the new result object which enables statistics, plotting ,etc..

While extracting the data from the result dictionary I used the class names to figure out what kind of object I am dealing with and also to use the class name as pandas index. If I use Pythons built in object.class.name this delivers the class of the object e. g. Bus or SimpleExtractionCHP. Since the classes Transport, Transformer and Sink all have a common subclass Simple the usage of delivers ambiguous object.class.name results.

Having unique core class names might be handy in some cases where objects are treated by there type. In my case it helps me to create "speaking names" since some object-uids in renpass-gis are not speaking for themselves. And I still remember Simon introducing a core class attribute "lower_name" to treat classes which is now also solved by using type(object).

My point: I think having unique class names could be handy for current and future applications

@oemof/oemof-main: What do you think?

Cheers
Cord

Creating a logging file

With commit 37afe31 one can use a helping function to initialise a logger within oemof.

Just import the logger module and initialise the logger at the very beginning of your app.

# Import logging module
from oemof.tools import logger

# initialise the logger
logger.define_logging()

Now everything higher than info will be displayed on the screen but everything (including debug) will be written to a logfile in the folder: ~/.oemof/log_files/

Of course you are able to customise this behaviour. For example if want just warnings and errors but no infos on the screen.

The screen output looks like this now:

11:40:24-INFO-Path for logging: /home/uwe/.oemof/log_files
11:40:24-INFO-Used oemof version: 18345077 @ features/two_region_example
11:40:25-INFO-Processing region: Landkreis Wittenberg (LanWit)
11:40:26-WARNING-Something odd happened...

The file output looks like this:

2015-12-10 11:41:14,628 - INFO - logger - Path for logging: /home/uwe/.oemof/log_files
2015-12-10 11:41:14,628 - INFO - logger - Used oemof version: 18345077 @ features/two_region_example
2015-12-10 11:41:14,693 - DEBUG - tools - Getting polygon from DB
2015-12-10 11:41:14,694 - INFO - two_regions_example - Processing region: Landkreis Wittenberg (LanWit)
2015-12-10 11:41:15,591 - DEBUG - models - Retrieving cp values from cp_values.hf5
2015-12-10 11:41:16,987 - WARNING - models - Something odd happened...

@oemof/oemof-main : Do we agree that we want to use logging messages within the code? I like the fact that you have a protocol in a file. This can help a lot while debugging. But than we need meaningful logging messages.

How to connect a power plant to an existing bus

Example: Natural gas power plant

To define the simple transformer, i have to pass the bus objects. So I have to find them in the list of entities of the energy system. As far as I understood oemof, all entities are automatically written to the list of entities in the object of the EnergySystem class.

As you suggested I am using tuples to identify the entities.

# Creating the energy system
ExampleSystem = es.EnergySystem()

# Creating regions
ExampleSystem.regions.append(es.Region(geom=GeoObj1, name=region1))
ExampleSystem.regions.append(es.Region(geom=GeoObj2, name=region2))

# Creating a global gas bus
Bus(uid=('bus', 'global', 'ngas') , type='ngas', price=60, sum_out_limit=10e10)

for region in list_of_regions
    # Creating a electricity bus for each region.
    Bus(uid=('bus', region.name, 'elec') , type='electricity', price=60, sum_out_limit=10e10, regions=[region])

    # Creating a gas power plant for each region
    transformer.Simple(
            uid=('ngas_power_plant', 'region.name', 'ngas', 'elec'),
            inputs=ExampleSystem.entities[??????],  # Global gas bus
            outputs=ExampleSystem.entities[??????],  # Local electricity bus
            in_max={('bus', 'global', 'elec'): None},
            out_max={('bus', region.name, 'elec'): 10000},
            eta=[0.4])

No investment in sources when add_out_limit is omitted

When I run the storage_invest.py with

source.FixedSource.optimization_options.update({'investment': True})

and no add_out_limit in the FixedSources pv and wind I get the following in lp file

0 <= _class__oemof_core_network_entities_components_sources_FixedSource___add_out(pv) <= 0
0 <= _class__oemof_core_network_entities_components_sources_FixedSource___add_out(wind) <= 0

which is wrong in my opinion since there is no possibility for the add_out variable to increase.

When I then in addition set out_max=[0] I get an infeasible problem as there can't be any generation capacity to meet the demand.

I pushed the modified storage_invest.py to the branch 'fix_invest_sources'.

Delete an orphan Bus

I created a lignite resource bus by hand but there is no lignite power plant in my region.

So I check all buses and want to delete the orphan ones. The following doesn't work:

buses = [obj for obj in MyEnergySystem.entities if isinstance(obj, Bus)]
for bus in buses:
    if len(bus.inputs) > 0 or len(bus.outputs) > 0:
        logging.debug('Bus {0} has connections.'.format(bus.type))
    else:
        logging.debug('Bus {0} has no connections and will be deleted.'.format(
            bus.type))
        MyEnergySystem.entities.remove(bus)

I assigned it to @gnn but maybe anybody else has an idea (@cswh, @simonhilpert, @ckaldemeyer).

Validation of results using tests

Within the development-phase of renpass-gis, results have to be validated. Since this is a general procedure for most models, the idea was to implement this using tests. If suitable, these tests can then be implemented into oemof_base afterwards.

Here are some quick ideas to start with (any further suggestions are welcome):

  • Bus balances: check if zero for all timesteps (regarding a small deviation "epsilon")
  • Transformers
    • Check if outputs divided through their efficiency equal their input for all timesteps
    • Check if full load hours are between 0 and 8760
  • Storages
    • Check storage balance over time (sum(inflow)>sum(outflow))
    • Check if SOC(t=0) is SOC(t=t_max)
  • Merit-Order-Checks
    • Check if order sort(marginal_prices) equals order of sort(full load hours)
    • Merit-Order plots (price vs. quantity): Check if all transformers on the right side of the required quantity (demand) are zero

@oemof/oemof-main : To you have any suggestions where to implement this? Using nose directly in the test folder?

@simonhilpert : Did I forget something?
@uvchik : I remember you telling me that you already had testing procedures at the RLI. Feel free to contribute!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.