This release contains new features but no changes to existing APIs.
- There is a new function
network.iplot()
which creates an interactive plot in Jupyter notebooks using the plotly library. This reveals bus and branch properties when the mouse hovers over them and allows users to easily zoom in and out on the network. See the SciGRID example for a showcase of this feature and also the (sparse) documentation :doc:`plotting`. - There is a new function
network.madd()
for adding multiple new components to the network. This is significantly faster than repeatedly callingnetwork.add()
and uses the functionsnetwork.import_components_from_dataframe()
andnetwork.import_series_from_dataframe()
internally. Documentation and examples can be found at :ref:`madd`. - There are new functions
network.export_to_hdf5()
andnetwork.import_from_hdf5()
for exporting and importing networks as single files in the Hierarchical Data Format. - In the
network.lopf()
function the KKT shadow prices of the branch limit constraints are now outputted as series calledmu_lower
andmu_upper
.
We thank Bryn Pickering for introducing us to plotly and helping to hack together the first working prototype using PyPSA.
This release contains some minor new features and a few minor but important API changes.
- There is a new component :ref:`global-constraints` for implementing
constraints that effect many components at once (see also the
LOPF subsection :ref:`global-constraints-opf`). Currently only
constraints related to primary energy (i.e. before conversion with
losses by generators) are supported, the canonical example being CO2
emissions for an optimisation period. Other primary-energy-related
gas emissions also fall into this framework. Other types of global
constraints will be added in future, e.g. "final energy" (for limits
on the share of renewable or nuclear electricity after conversion),
"generation capacity" (for limits on total capacity expansion of
given carriers) and "transmission capacity" (for limits on the total
expansion of lines and links). This replaces the ad hoc
network.co2_limit
attribute. If you were using this, instead ofnetwork.co2_limit = my_cap
donetwork.add("GlobalConstraint", "co2_limit", type="primary_energy", carrier_attribute="co2_emissions", sense="<=", constant=my_cap)
. The shadow prices of the global constraints are automatically saved innetwork.global_constraints.mu
. - The LOPF output
network.buses_t.marginal_price
is now defined differently ifnetwork.snapshot_weightings
are not 1. Previously if the generator at the top of the merit order hadmarginal_cost
c and the snapshot weighting was w, themarginal_price
was cw. Now it is c, which is more standard. See also :ref:`nodal-power-balance`. network.pf()
now returns a dictionary of pandas DataFrames, each indexed by snapshots and sub-networks.converged
is a table of booleans indicating whether the power flow has converged;error
gives the deviation of the non-linear solution;n_iter
the number of iterations required to achieve the tolerance.network.consistency_check()
now includes checking for potentially infeasible values ingenerator.p_{min,max}_pu
.- The PyPSA version number is now saved in
network.pypsa_version
. In future versions of PyPSA this information will be used to upgrade data to the latest version of PyPSA. network.sclopf()
has anextra_functionality
argument that behaves like that fornetwork.lopf()
.- Component attributes which are strings are now better handled on import and in the consistency checking.
- There is a new generation investment screening curve example showing the long-term equilibrium of generation investment for a given load profile and comparing it to a screening curve analysis.
- There is a new logging example that demonstrates how to control the level of logging that PyPSA reports back, e.g. error/warning/info/debug messages.
- Sundry other bug fixes and improvements.
- All examples have been updated appropriately.
Thanks to Nis Martensen for contributing the return values of
network.pf()
and Konstantinos Syranidis for contributing the
improved network.consistency_check()
.
This release mostly contains new features with a few minor API changes.
- Unit commitment as a MILP problem is now available for generators in
the Linear Optimal Power Flow (LOPF). If you set
committable == True
for the generator, an addition binary online/offline status is created. Minimum part loads, minimum up times, minimum down times, start up costs and shut down costs are implemented. See the documentation at :ref:`unit-commitment` and the unit commitment example. Note that a generator cannot currently have both unit commitment and capacity expansion optimisation. - Generator ramping limits have also been implemented for all generators. See the documentation at :ref:`ramping` and the unit commitment example.
- Different mathematically-equivalent formulations for the Linear Optimal Power Flow (LOPF) are now documented in :ref:`formulations` and the arXiv preprint paper Linear Optimal Power Flow Using Cycle Flows. The new formulations can solve up to 20 times faster than the standard angle-based formulation.
- You can pass the
network.lopf
function thesolver_io
argument for pyomo. - There are some improvements to network clustering and graphing.
- API change: The attribute
network.now
has been removed since it was unnecessary. Now, if you do not pass asnapshots
argument to network.pf() or network.lpf(), these functions will default tonetwork.snapshots
rather thannetwork.now
. - API change: When reading in network data from CSV files, PyPSA will parse snapshot dates as proper datetimes rather than text strings.
João Gorenstein Dedecca has also implemented a MILP version of the transmission expansion, see https://github.com/jdedecca/MILP_PyPSA, which properly takes account of the impedance with a disjunctive relaxation. This will be pulled into the main PyPSA code base soon.
This is a major release which contains important new features and changes to the internal API.
- Standard types are now available for lines and transformers so that you do not have to calculate the electrical parameters yourself. For lines you just need to specify the type and the length, see :ref:`line-types`. For transformers you just need to specify the type, see :ref:`transformer-types`. The implementation of PyPSA's standard types is based on pandapower's standard types. The old interface of specifying r, x, b and g manually is still available.
- The transformer model has been substantially overhauled, see
:ref:`transformer-model`. The equivalent model now defaults to the
more accurate T model rather than the PI model, which you can control
by setting the attribute
model
. Discrete tap steps are implemented for transformers with types. The tap changer can be defined on the primary side or the secondary side. In the PF there was a sign error in the implementation of the transformerphase_shift
, which has now been fixed. In the LPF and LOPF angle formulation thephase_shift
has now been implemented consistently. See the new transformer example. - There is now a rudimentary import function for pandapower networks, but it doesn't yet work with all switches and 3-winding transformers.
- The object interface for components has been completely
removed. Objects for each component are no longer stored in
e.g.
network.lines["obj"]
and the descriptor interface for components is gone. You can only access component attributes through the dataframes, e.g.network.lines
. - Component attributes are now defined in CSV files in
pypsa/component_attrs/
. You can access these CSVs in the code via the dictionarynetwork.components
, e.g.network.components["Line"]["attrs"]
will show a pandas DataFrame with all attributes and their types, defaults, units and descriptions. These CSVs are also sourced for the documentation in :doc:`components`, so the documentation will always be up-to-date. - All examples have been updated appropriately.
This release contains bug fixes, a minor new feature and more warnings.
- The unix-only library
resource
is no longer imported by default, which was causing errors for Windows users. - Bugs in the setting and getting of time-varying attributes for the object interface have been fixed.
- The
Link
attributeefficiency
can now be make time-varying so that e.g. heat pump Coefficient of Performance (COP) can change over time due to ambient temperature variations (see the heat pump example). network.snapshots
is now cast to apandas.Index
.- There are new warnings, including when you attach components to non-existent buses.
Thanks to Marius Vespermann for promptly pointing out the resource
bug.
This is a major release which contains changes to the API, particularly regarding time-varying component attributes.
network.generators_t
are no longer pandas.Panels but dictionaries of pandas.DataFrames, with variable columns, so that you can be flexible about which components have time-varying attributes; please read :ref:`time-varying` carefully. Essentially you can either set a component attribute e.g.p_max_pu
ofGenerator
, to be static by setting it in the DataFramenetwork.generators
, or you can let it be time-varying by defining a new column labelled by the generator name in the DataFramenetwork.generators_t["p_max_pu"]
as a series, which causes the static value innetwork.generators
for that generator to be ignored. The DataFramenetwork.generators_t["p_max_pu"]
now only includes columns which are specifically defined to be time-varying, thus saving memory.- The following component attributes can now be time-varying:
Link.p_max_pu
,Link.p_min_pu
,Store.e_max_pu
andStore.e_min_pu
. This allows the demand-side management scheme of https://arxiv.org/abs/1401.4121 to be implemented in PyPSA. - The properties
dispatch
,p_max_pu_fixed
andp_min_pu_fixed
ofGenerator
andStorageUnit
are now removed, because the ability to makep_max_pu
andp_min_pu
either static or time-varying removes the need for this distinction. - All messages are sent through the standard Python library
logging
, so you can control the level of messages to be e.g.debug
,info
,warning
orerror
. All verbose switches and print statements have been removed. - There are now more warnings.
- You can call
network.consistency_check()
to make sure all your components are well defined; see :doc:`troubleshooting`.
All examples have been updated to accommodate the changes listed below.
This release fixes a single library dependency issue:
- pf: A single line has been fixed so that it works with new pandas versions >= 0.19.0.
We thank Thorben Meiners for promptly pointing out this issue with the new versions of pandas.
This release fixes a single critical bug:
- opf: The latest version of Pyomo (4.4.1) had a bad interaction with pandas when a pandas.Index was used to index variables. To fix this, the indices are now cast to lists; compatibility with less recent versions of Pyomo is also retained.
We thank Joao Gorenstein Dedecca for promptly notifying us of this bug.
Like the 0.5.0 release, this release contains API changes, which complete the integration of sector coupling. You may have to update your old code. Models for Combined Heat and Power (CHP) units, heat pumps, resistive Power-to-Heat (P2H), Power-to-Gas (P2G), battery electric vehicles (BEVs) and chained hydro reservoirs can now be built (see the sector coupling examples). The refactoring of time-dependent variable handling has been postponed until the 0.7.0 release. In 0.7.0 the object interface to attributes may also be removed; see below.
All examples have been updated to accommodate the changes listed below.
- components, opt: A new
Store
component has been introduced which stores energy, inheriting the energy carrier from the bus to which it is attached. The component is more fundamental than theStorageUnit
, which is equivalent to aStore
and twoLink
for storing and dispatching. TheGenerator
is equivalent to aStore
with a lossyLink
. There is an example which shows the equivalences. - components, opt: The
Source
component and theGenerator
attributegen.source
have been renamedCarrier
andgen.carrier
, to be consistent with thebus.carrier
attribute. Please update your old code. - components, opt: The
Link
attributeslink.s_nom*
have been renamedlink.p_nom*
to reflect the fact that the link can only dispatch active power. Please update your old code. - components, opt: The
TransportLink
andConverter
components, which were deprecated in 0.5.0, have been now completely removed. Please update your old code to useLink
instead.
The intention is to have only the pandas DataFrame interface for accessing component attributes, to make the code simpler. The automatic generation of objects with descriptor access to attributes may be removed altogether.
- examples: Patterns of for loops through
network.components.obj
have been removed. - components: The methods on
Bus
likebus.generators()
andbus.loads()
have been removed. - components:
network.add()
no longer returns the object.
- components, opf: Unlimited upper bounds for
e.g.
generator.p_nom_max
orline.s_nom_max
were previous set usingnp.nan
; now they are set usingfloat("inf")
which is more logical. You may have to update your old code accordingly. - components: A memory leak whereby references to
component.network
were not being correctly deleted has been fixed.
This is a relatively major release with some API changes, primarily aimed at allowing coupling with other energy carriers (heat, gas, etc.). The specification for a change and refactoring to the handling of time series has also been prepared (see :ref:`time-varying`), which will be implemented in the next major release PyPSA 0.6.0 in the late summer of 2016.
An example of the coupling between electric and heating sectors can be
found in the GitHub repository at
pypsa/examples/coupling-with-heating/
and at
http://www.pypsa.org/examples/lopf-with-heating.html.
- components: To allow other energy carriers, the attribute
current_type
fur buses and sub-neworks (sub-networks inherit the attribute from their buses) has been replaced bycarrier
which can take generic string values (such as "heat" or "gas"). The values "DC" and "AC" have a special meaning and PyPSA will treat lines and transformers within these sub-networks according to the load flow equations. Other carriers can only have single buses in sub-networks connected by passive branches (since they have no load flow). - components: A new component for a controllable directed link
Link
has been introduced;TransportLink
andConverter
are now deprecated and will be removed soon in an 0.6.x release. Please move your code over now. See :ref:`controllable-link` for more details and a description of how to update your code to work with the newLink
component. All the examples in the GitHub repository inpypsa/examples/
have been updated to us theLink
. - graph: A new sub-module
pypsa.graph
has been introduced to replace most of the networkx functionality with scipy.sparse methods, which are more performant the the pure python methods of networkx. The discovery of network connected components is now significantly faster. - io: The function
network.export_to_csv_folder()
has been rewritten to only export non-default values of static and series component attributes. Static and series attributes of all components are not exported if they are default values. The functionality to selectively export series has been removed from the export function, because it was clumsy and hard to use. See :ref:`export-csv` for more details. - plot: Plotting networks is now more performant (using matplotlib LineCollections) and allows generic branches to be plotted, not just lines.
- test: Unit testing for Security-Constrained Linear Optimal Power Flow (SCLOPF) has been introduced.
This release improved the non-linear power flow performance and included other small refactorings:
- pf: The non-linear power flow
network.pf()
now accepts a list of snapshotsnetwork.pf(snapshots)
and has been refactored to be much more performant. - pf: Neither
network.pf()
nornetwork.lpf()
accept thenow
argument anymore - for the power flow on a specific snapshot, either setnetwork.now
or pass the snapshot as an argument. - descriptors: The code has been refactored and unified for each simple descriptor.
- opt: Constraints now accept both an upper and lower bound with
><
. - opf: Sub-optimal solutions can also be read out of pyomo.
This was mostly a bug-fixing and unit-testing release:
- pf: A bug was fixed in the full non-linear power flow, whereby the reactive power output of PV generators was not being set correctly.
- io: When importing from PYPOWER ppc, the generators, lines, transformers and shunt impedances are given names like G1, G2, ..., L1, T1, S1, to help distinguish them. This change was introduced because the above bug was not caught by the unit-testing because the generators were named after the buses.
- opf: A Python 3 dict.keys() list/iterator bug was fixed for the spillage.
- test: Unit-testing for the pf and opf with inflow was improved to catch bugs better.
We thank Joao Gorenstein Dedecca for a bug fix.
Additional features:
- New module
pypsa.contingency
for contingency analysis and security-constrained LOPF - New module
pypsa.geo
for basic manipulation of geographic data (distances and areas) - Re-formulation of LOPF to improve optimisation solving time
- New objects pypsa.opt.LExpression and pypsa.opt.LConstraint to make the bypassing of pyomo for linear problem construction easier to use
- Deep copying of networks with
network.copy()
(i.e. all components, time series and network attributes are copied) - Stricter requirements for PyPI (e.g. pandas must be at least version 0.17.1 to get all the new features)
- Updated SciGRID-based model of Germany
- Various small bug fixes
We thank Steffen Schroedter, Bjoern Laemmerzahl and Joao Gorenstein Dedecca for comments and bug fixes.
Additional features:
network.lpf
can be called on an iterable ofsnapshots
i.e.network.lpf(snapshots)
, which is more performant that callingnetwork.lpf
on each snapshot separately.- Bug fix on import/export of transformers and shunt impedances (which were left out before).
- Refactoring of some internal code.
- Better network clustering.
In this release some minor API changes were made:
- The Newton-Raphson tolerance
network.nr_x_tol
was moved to being an argument of the functionnetwork.pf(x_tol=1e-6)
instead. This makes more sense and is then available in the docstring ofnetwork.pf
. - Following similar reasoning
network.opf_keep_files
was moved to being an argument of the functionnetwork.lopf(keep_files=False)
.
In this release some minor API changes were made:
- Optimised capacities of generators/storage units and branches are now written to p_nom_opt and s_nom_opt respectively, instead of over-writing p_nom and s_nom
- The p_max/min limits of controllable branches are now p_max/min_pu per unit of s_nom, for consistency with generation and to allow unidirectional HVDCs / transport links for the capacity optimisation.
- network.remove() and io.import_series_from_dataframe() both take as argument class_name instead of list_name or the object - this is now fully consistent with network.add("Line","my line x").
- The booleans network.topology_determined and network.dependent_values_calculated have been totally removed - this was causing unexpected behaviour. Instead, to avoid repeated unnecessary calculations, the expert user can call functions with skip_pre=True.
In this release the pandas.Panel interface for time-dependent variables was introduced. This replaced the manual attachment of pandas.DataFrames per time-dependent variable as attributes of the main component pandas.DataFrame.