Release Notes#
v0.31.0 (1st October 2024)#
New
active
attribute (PyPSA/PyPSA#1038)A new attribute for one-port and branch components active was added. If set to true (default), the asset is considered active for all functionality, including optimization and power flow calculation. If set to false, the asset is considered inactive and is excluded from the optimization, power flow and statistics modules.
The active attribute can be thought of as a global filter on the components. When running a multi-horizon optimization, the active attribute is considered a global condition for each horizon. Then assets are considered active only if active is true and the investment period falls within the lifetime of the asset.
New attributes for the generator component (PyPSA/PyPSA#1047)
e_sum_min
ande_sum_max
add a new constraint and allow to set the minimum and maximum total energy that can be generated by the generator over one optimization horizon.
New
n.add
method (PyPSA/PyPSA#896)n.add
now handles the addition of a single or multiple components, has more robust index alignment checks allows to overwrite existing components using the new argumentoverwrite
. Because of the more strict alignment checks, this might be a breaking change for some users.Therefore the methods
n.madd
andn.mremove
are now deprecated and will point to their generalised counterparts.
New function
n.optimize_and_run_non_linear_powerflow
was added to the set of abstract optimize functions. This function optimizes the network and runs a non-linear power flow calculation afterwards. (PyPSA/PyPSA#1038)API and structural changes:
The
Component
object is now a refactored stand-alone class. This is ongoing work and will change further in future releases. (PyPSA/PyPSA#1038)The
pypsa.SubNetwork
class has new methods df, pnl, component to ease the access of component data for a subnetwork. Use it with e.g. subnetwork.df(“Generator”) and alike. (PyPSA/PyPSA#1038)n.df
andn.pnl
have been renamed ton.static
andn.dynamic
. But n.df and n.pnl are still available and can be used as aliases without any deprecation warning for now. (PyPSA/PyPSA#1028)
See full list of changes here.
v0.30.3 (24th September 2024)#
Bugfix in the post discretization for
Links
with a maximum capacity. Furthermore, giving the option to build out only multiples of the specified unit_size or allowing to use the full maximum capacity. (PyPSA/PyPSA#1039)See full list of changes here.
v0.30.2 (11th September 2024)#
Bugfix in operational limit global constraints, which now directly uses the carrier of the
Store
rather than the carrier of the bus it is attached to. (PyPSA/PyPSA#1029)See full list of changes here.
v0.30.1 (9th September 2024)#
Added option for importing and exporting CSV, netCDF and HDF5 files in cloud object storage. This requires the installation of the optional dependency
cloudpathlib
, e.g. viapip install pypsa[cloudpath]
.Bugfix of
n.plot()
when single buses have no coordinates.See full list of changes here.
v0.30.0 (30th August 2024)#
Added
n.explore()
function based onfolium
andgeopandas
to interactively explore networks. (PyPSA/PyPSA#1009)Added new
spill_cost
input parameter for storage units which penalizes spilling excess energy. (PyPSA/PyPSA#1012)Added new
marginal_cost_storage
input parameter for stores and storage units to represent the cost of storing energy in currency/MWh/h. (PyPSA/PyPSA#603)Added type annotations to all functions. (PyPSA/PyPSA#1010)
Updated documentation. (PyPSA/PyPSA#1004)
See full list of changes here.
v0.29.0 (31st July 2024)#
Removed
n.lopf()
pyomo-based and nomopyomo-based optimisation modules. Use linopy-based optimization withn.optimize()
instead. (PyPSA/PyPSA#884)HiGHS becomes the new default solver for
n.optimize()
. (PyPSA/PyPSA#884)Changes to the
statistics
module:The statistics functions
n.statistics.capex()
,n.statistics.installed_capex()
, andexpanded_capex
now have an optionalcost_attribute
argument, which defaults to capital_cost. The default behavior of the functions is not changed. (PyPSA/PyPSA#989)The functions
n.statistics.optimal_capacity()
andn.statistics.expanded_capacity()
now return positive and negative capacity values if abus_carrier
is selected. Positive values correspond to production capacities, negative values to consumption capacities. (PyPSA/PyPSA#885)The statistics module now supports the
nice_name
argument for bus carriers. Previously, nice names were only supported for components carriers. (PyPSA/PyPSA#991)The statistics module now features functionality to set global style parameters (e.g.
nice_names
,drop_zero
andround
) which is then applied to all statistics methods without the need to set them individually. To set parameters one can runn.statistics.set_parameters(nice_names=False, round=2)
and to view current parameters settingn.statistics.parameters
. (PyPSA/PyPSA#886)
Changes to the
clustering
module:Add attribute-based exemptions for clustering lines and links. With the argument
custom_line_groupers
in the functionaggregatelines()
one can specify additional columns besidesbus0
andbus1
to consider as unique criteria for clustering. This is useful, for example, to avoid the aggregation of lines/links with differentbuild_year
orcarrier
. (PyPSA/PyPSA#982)
Changes to the
plot
module:Add option to add semicircle legends by running
pypsa.plot.add_legend_semicircle(ax, sizes=[1000/scaling_factor], labels=["1 GWh"])
. (PyPSA/PyPSA#986)Add functionality to provide list of colors in
add_legend_lines()
. (PyPSA/PyPSA#902)
Bugfixes:
The security-constrained optimization via
n.optimize.optimize_security_constrained()
was fixed to correctly handle multiple subnetworks. (PyPSA/PyPSA#946)The global constraint on the total transmission costs now includes the weight of the investment periods and persistence of investment costs of active assets in multi-horizon optimisations.
Retain investment periods and weightings when clustering networks. (PyPSA/PyPSA#891)
Removed performance regression of
statistics
module. (PyPSA/PyPSA#990)When adding bus ports on the fly with add methods, the dtype of the freshly created column is now fixed to string. (PyPSA/PyPSA#893)
Using timezone information in n.snapshots raises an error now, since it leads to issues with numpy/ xarray. (PyPSA/PyPSA#976)
Improvements to consistency checks and model debugging:
When adding components with bus ports greater than 1, e.g. bus2, pypsa checks if the bus exists and prints a warning if it does not. (PyPSA/PyPSA#893)
Also check for missing values of default attributes in the n.consistency_check() function. (PyPSA/PyPSA#903)
Restructure
n.consistency_check()
. (PyPSA/PyPSA#918, PyPSA/PyPSA#920)Add option n.optimize(compute_infeasibilities=True) to compute Irreducible Inconsistent Subset (IIS) in case an infeasibility was encountered and Gurobi is installed. (PyPSA/PyPSA#978)
Improved error messages. (PyPSA/PyPSA#897)
Add functionality to compare two networks for equality via equality operator (
==
). (PyPSA/PyPSA#924)Add single-node electricity-only and sector-coupled capacity expansion example. (PyPSA/PyPSA#904)
Added new line type “Al/St 490/64 4-bundle 380.0”. (PyPSA/PyPSA#887)
Use
ruff
. (PyPSA/PyPSA#900, PyPSA/PyPSA#901)Improve CI and auto-release process. (PyPSA/PyPSA#907, PyPSA/PyPSA#921)
Restructured API reference. (PyPSA/PyPSA#960)
Compatibility with
numpy>=2.0
. (PyPSA/PyPSA#932)See full list of changes here.
v0.28.0 (8th May 2024)#
When using iterative optimisation functionality
n.optimize_transmission_expansion_iteratively()
, add option to discretize optimised line and link capacities in the final iteration based on new keyword argumentsline_unit_size
,link_unit_size
,line_threshold
andlink_threshold
. This allows to round the optimised capacities to a multiple of the unit size based on the threshold. (PyPSA/PyPSA#871)A new function
n.merge()
was added allowing the components and time-dependent data of one network to be added to another network. The function is also available vian + m
with default settings. The function requires disjunct component indices and identical snapshots and snapshot weightings. (PyPSA/PyPSA#783)New features in the statistics module (PyPSA/PyPSA#860):
The statistics module introduces a new keyword argument
at_port
to all functions. This allows considering the port of a component when calculating statistics. Depending on the function, the default ofat_port
is set toTrue
orFalse
, for example for the dispatch all ports are considered.The statistics module now supports an optional
port
argument ingroupby
functions. This allows to group statistics while considering the port of a component.The
statistics.revenue
function introduces a new keyword argumentkind
to optionally calculate the revenue based on theinput
commodity or theoutput
commodity of a component.The
statistics.energy_balance
function introduces a new keyword argumentkind
to optionally calculate thesupply
andwithdrawal
of a component.Deprecation warnings are added to the statistics module for the functionalities that will be removed in the next major release.
Updated
environment_doc.yml
to include the latest requiredpip
dependencies for the documentation environment. (PyPSA/PyPSA#862)Bugfix: calling
n.create_model()
orn.optimize()
when a global operational limit is defined will no longer set the carrier attribute of stores to the carrier of the bus they are attached to. (PyPSA/PyPSA#880)Added warning to
plot.py
with instructions to handle the case where therequests
dependency is missing. (PyPSA/PyPSA#882)Bugfix: calling
n.optimize.*
functions (e.g.n.optimize.optimize_mga
) now correctly returns each functions return values. (PyPSA/PyPSA#871)
v0.27.1 (22nd March 2024)#
Fixed sometimes-faulty total budget calculation for single-horizon MGA optimisations.
Fixed assignment of active assets in multi-horizon optimisation with
n.optimize
.Fixed setting of investment periods when copying a multi-horizon network.
Always use name and mask keys in variable and constraint assignment to protect against future changes in argument order.
Rewrite function
get_switchable_as_dense
so that it consumes less memory when calling it with large dataframes.Fix of the capex description in the attribute CSV files.
v0.27.0 (18th February 2024)#
Bugfix: If plotting a network map with split buses (
n.plot(bus_split_circles=True)
), the bus sizes are now scaled by factor 2 to account for the fact that the bus sizes are split into half circles. This makes the area scaling of the buses consistent with the area of non-split buses.The global constraint
define_tech_capacity_expansion_limit
now also takes branch components into account. If defined per bus, thebus0
of the branch is considered as a reference bus.Bugfixes in building of global constraints in multi-horizon optimisations.
Fixed total budget calculation for MGA on multi-horizon optimisations.
The
extra_functionality
argument is now also supported insolve_model
accessor.optimize_mga
now returns the solver termination status and condition.The deprecated functions
_make_consense
,aggregategenerators
,get_buses_linemap_and_lines
andget_clustering_from_busmap
were removed.The minimum
networkx
version was bumped from1.10
to2
.pyomo
is no longer supported for Python 3.12 or higher.
v0.26.3 (25th January 2024)#
Bugfix: With line transmission losses there was a sign error in the calculation of the line capacity constraints.
Approximated transmission losses of lines are now stored after optimisation as the difference between
n.lines_t.p0
andn.lines_t.p1
so that they appear in the energy balance (e.g.n.statistics.energy_balance()
) and when calculating losses withn.lines_t.p0 + n.lines_t.p1
.
v0.26.2 (31st December 2023)#
Bugfix in the definition of spillage variables for storage units. Previously, the spillage variable creation was skipped in some cases due to a wrong condition check even though there was a positive inflow.
v0.26.1 (29th December 2023)#
The output attribute
n_mod
introduced in the previous version was removed since it contains duplicate information. Calculate the number of expanded modules withp_nom_opt / p_nom_mod
instead.Bugfix in MGA function to correctly parse the
sense
keyword argument.Fix strict type compatibility issues with
pandas>=2.1
causing problems for clustering.Removed
numexpr
version constraint.
v0.26.0 (4th December 2023)#
New Features
The
Network
class has a new component for geometric shapes undern.shapes
. It consists of ageopandas
dataframe which can be used to store network related geographical data (for plotting, calculating potentials, etc). The dataframe has the columns geometry, component, idx and type. The columns component, idx and type do not require specific values, but allow for storing information about which components the shapes belong to. The coordinate reference system (CRS) of the shapes can be accessed and set via a new attributen.crs
. For a transition period, the attributen.srid
, which independently refers to the projection of the bus coordinates, is kept.Improvements to the network statistics module:
The statistics module now supports the consideration of multi-port links. An additional argument bus_carrier was added to the statistics functions to select the components that are attached to buses of a certain carrier.
The statistics module now supports the consideration of multiple investment periods. As soon as
n.snapshots
is a MultiIndex, the network statistics are calculated separately for each investment period.A new function
transmission
was added to the statistics accessor. This function considers all lines and links that connect buses of the same carrier.The statistics functions now support the selection of single components in the
comps
argument.
The plotting function
n.plot()
now supports plotting of only a subset of network components by allowing that arguments likebus_sizes
,link_widths
orlink_colors
do no longer require to contain the full set of indices of a component.Add option to specify time-varying ramp rates for generators and links (
ramp_limit_up
andramp_limit_down
, e.g. undern.links_t.ramp_limit_up
).Added attributes
p_nom_mod
,e_nom_mod
, ands_nom_mod
to components to consider capacity modularity. When this attribute is non-zero and the component is extendable, the component’s capacity can only be extended in multiples of the capacity modularity. The optimal number of components is stored asn_mod
(such thatp_nom_mod * n_mod == p_nom_opt
). The default is kept such that extendable components can be expanded continuously.
Bugfixes and Compatibiliity
Bugfix: In rolling horizon optimisation with unit commitment constraints, the generator status of the previously optimized time step is now considered.
Bugfix: Allow optimising the network for just subset of investment periods by using
n.optimize(multi_investment_periods=True, snapshots=...)
.Bugfix: The function
n.import_from_netcdf()
failed when trying to import data from anxarray
object.Bugfix: Fix global constraints for primary energy and transmission volume limits for networks with multiple investment periods.
Bugfix: Fix stand-by-costs optimization for latest
linopy
version.Resolve performance regression for multi-decade optimisation in highly meshed networks.
Compatibility with
pandas==2.1
.Added Python 3.12 to CI and supported Python versions.
v0.25.2 (30th September 2023)#
Add option to enable or disable nice carrier name in the statistics module, e.g.
n.statistics(nice_name=False)
.Add example in documentation for the statistics module.
Add example for stochastic optimization with PyPSA to the documentation.
Extended documentation for multi-decade optimization.
Bugfix: Use of
nice_names
keyword argument inn.statistics.energy_balance()
.Bugfix: Correctly handle
p_nom
orp_nom_opt
in power flow distributed slack.Bugfix: After the optimization the right-hand side and sign of global constraints were previously overwritten by altered values.
Bugfix: In netCDF export, typecasting to float32 after setting the compression encoding led to ignored compression encodings.
Bugfix: Handle solver options for CBC and GLPK for
n.lopf(pyomo=False)
.Bugfix: Handle cases with multi-decade optimisation, activated transmission limit and an empty list of lines or DC links.
v0.25.1 (27th July 2023)#
New Features
The function
get_clustering_from_busmap
has a new argumentline_strategies
.The
n.optimize()
function gets a new keyword argumentassign_all_duals=False
which controls whether all dual values or only those that already have a designated place in the network are assigned. (PyPSA/PyPSA#635)
Changes
The function
get_buses_linemap_and_lines
was deprecated, in favor of direct use ofaggregatebuses
andaggregate_lines
.Improve logging printout for rolling horizon optimization. (PyPSA/PyPSA#697, PyPSA/PyPSA#699)
The CI environment handling was migrated to
micromamba
(PyPSA/PyPSA#688).
Bugfixes
The aggregation functions in the clustering module were adjusted to correctly handle infinity values (see pandas-dev/pandas#54161 for more details). (PyPSA/PyPSA#684)
The unit commitment formulation with a rolling horizon horizon was fixed in case of non-committable and committable generators with ramp limits. (PyPSA/PyPSA#686)
The clustering functionality was fixed in case of passing a subset of carriers that should be aggregated. (PyPSA/PyPSA#696)
When clustering, allow safe clustering of component attributes which are both static and dynamic. (PyPSA/PyPSA#700)
When assigning a new user-defined variable to the underlying optimization model, the assignment of the solution resulted in an error if the variable name did not match the pattern
{Component}-{Varname}
. This has been fixed by ignoring variables that do not match the pattern during solution assignment. (PyPSA/PyPSA#693)Multilinks are now also handled automatically when importing a network from file. (PyPSA/PyPSA#702)
Multilink default efficiencies are always set to 1.0. (PyPSA/PyPSA#701)
For linearized unit commitment relaxation, some tightening additional constraints are only valid if start-up and shut-down costs are equal. These constraints are now skipped if this is not the case and a warning message is printed. (PyPSA/PyPSA#690)
Fix division in capacity factor calculation in statistics module when not aggregating in the time dimension. (PyPSA/PyPSA#687)
v0.25.0 (13th July 2023)#
New Features
Stand-by costs: PyPSA now supports stand-by cost terms. A new column
stand_by_cost
was added to generators and links. The stand-by cost is added to the objective function when callingn.optimize()
. (PyPSA/PyPSA#659)Rolling horizon function: The
n.optimize
accessor now provides functionality for rolling horizon optimisation usingn.optimize.optimize_with_rolling_horizon()
which splits whole optimization of the whole time span into multiple subproblems which are solved consecutively. This is useful for operational optimizations with a high spatial resolution. (PyPSA/PyPSA#668)Modelling-to-generate-alternatives (MGA) function The
n.optimize
accessor now provides functionality for running modelling-to-generate-alternatives (MGA) on previously solved networks usingn.optimize.optimize_mga(slack=..., weights=...)
. This is useful for exploring the near-optimal feasible space of the network. (PyPSA/PyPSA#672)
Changes
Multilinks by default: Links with multiple inputs/outputs are now supported by default. The Link component attributes are automatically extended if a link with
bus2
,bus3
, etc. are added to the network. Overriding component attributes at network initialisation is no longer required. (PyPSA/PyPSA#669)Spatial clustering refactored: The spatial clustering module was refactored. The changes lead to performance improvements and a more consistent clustering API. (PyPSA/PyPSA#673)
The network object has a new accessor
cluster
which allows accessing clustering routines from the network itself. For example,n.cluster.cluster_spatially_by_kmeans
returns a spatially clustered version of the network.The default clustering strategies were refined. Per default, columns like
efficiency
andp_max_pu
are now aggregated by the capacity weighted mean.The clustering module now applies the custom strategies to time-dependant data.
The function
pypsa.clustering.spatial.get_clustering_from_busmap
andpypsa.clustering.spatial.aggregategenerators
now allows the passing of a list of buses for which aggregation of all carriers is desired. Generation from a carrier at a bus is aggregated now if: It is either in the passed list of aggregated carriers, or in the list of aggregated buses.Take generator strategies for time-series into account. Before, time-series would always be aggregated by summing. (PyPSA/PyPSA#670)
The deprecated
networkclustering
module was removed. (PyPSA/PyPSA#675)
A new function get_country_and_carrier was added to the statistics module in order to group statistics by country and carrier. (PyPSA/PyPSA#678)
NetCDF file compression is now disabled by default when exporting networks. (PyPSA/PyPSA#679)
Breaking Changes
The
Clustering
class no longer contains a positive and negative linemap.Outdated examples were removed. (PyPSA/PyPSA#674)
Bugfixes
In the statistics module, the calculation of operational costs of storage units was corrected. (PyPSA/PyPSA#671)
v0.24.0 (27th June 2023)#
PyPSA now supports quadratic marginal cost terms. A new column marginal_cost_quadratic was added to generators, links, stores and storage units. The quadratic marginal cost is added to the objective function when calling
n.optimize()
. This requires a solver that is able to solve quadratic problems, for instance, HiGHS, Gurobi, Xpress, or CPLEX.The statistics function now allows calculating energy balances
n.statistics.energy_balance()
and dispatchn.statistics.dispatch()
, as well as time series (e.g.n.statistics.curtailment(aggregate_time=False)
). The energy balance can be configured to yield energy balance time series for each bus.The statistics function
n.statistics()
now also supports the calculation of the market values of components.The function
n.set_snapshots()
now takes two optional keyword arguments;default_snapshot_weightings
to change the default snapshot weightings, andweightings_from_timedelta
to compute the weights if snapshots are of typepd.DatetimeIndex
.The function
n.lopf()
is deprecated in favour of the linopy-based implementationn.optimize()
and will be removed in PyPSA v1.0. We will have a generous transition period, but please start migrating yourextra_functionality
functions, e.g. by following our migration guide.The module
pypsa.networkclustering
was moved topypsa.clustering.spatial
. The modulepypsa.networkclustering
is now deprecated but all functionality will continue to be accessible until PyPSA v0.25.Bug fix in linearized unit commitment implementation correcting sign.
The minimum required version of
linopy
is now0.2.1
.Dropped support for Python 3.8. The minimum required version of Python is now 3.9.
v0.23.0 (10th May 2023)#
Transmission losses can now be represented during optimisation with
n.optimize()
orn.lopf()
using a piecewise linear approximation of the loss parabola as presented in this paper. The number of segments can be chosen with the argumentn.optimize(transmission_losses=3)
. The default remains that transmission losses are neglected withn.optimize(transmission_losses=0)
, and analogously forn.lopf(pyomo=True)
andn.lopf(pyomo=False)
. [#462]Efficiencies and standing losses of stores, storage units and generators can now be specified as time-varying attributes (
efficiency
,efficiency_dispatch
,efficiency_store
,standing_loss
). For example, this allows specifying temperature-dependent generator efficiencies or evaporation in hydro reservoirs. [#572]Unit commitment constraints (ramp limits, start up and shut down costs) can now also be applied to links in addition to generators. This is useful to model the operational restrictions of fuel synthesis plants. [#582]
Added implementation for a linearized unit commitment approximation (LP-based) that can be activated when calling
n.optimize(linearized_unit_commitment=True)
. The implementation follows Hua et al. (2017), 10.1109/TPWRS.2017.2735026. This functionality is not implemented forn.lopf()
. [#472]NetCDF (
.nc
) and HDF5 (.h5
) network files can now be read directly from URL:pypsa.Network("https://github.com/PyPSA/PyPSA/raw/master/examples/scigrid-de/scigrid-with-load-gen-trafos.nc")
[#569]Networks are now compressed when exporting the NetCDF
n.export_to_netcdf(...)
step using the native compression feature of netCDF files. Additionally, a typecasting option from float64 to float 32 was added. Existing network files are not affected. To also compress existing networks, load and save them usingxarray
with compression specified, see the xarray documentation for details. The compression can be disabled withn.export_to_netcdf(compression=None)
. Usen.export_to_netcdf(float32=True, compression={'zlib': True, 'complevel': 9, 'least_significant_digit': 5})
for high compression. [#583, #614]Time aggregation for OPEX, curtailment, supply, withdrawal, and revenue now default to ‘sum’ rather than ‘mean’.
A new type of
GlobalConstraint
called operational_limit is now supported through then.optimize()
function. It allows to limit the total production of a carrier analogous to primary_energy_limit with the difference that it applies directly to the production of a carrier rather than to an attribute of the primary energy use. [#618]The attributes
lifetime
andbuild_year
are now aggregated with a capacity-weighted mean when clustering the network. Previously, these attributes had to carry identical values for components that were to be merged. [#571]To enable better backwards compatibility with the
n.lopf()
function, then.optimize()
functions has now the explicit keyword argumentsolver_options
. It takes a dictionary of options passed to the solver. Before, these were passed as keyword arguments to then.optimize()
function. Note that both functionalities are supported. [#595]Fixed interference of io routines with linopy optimisation [#564, #567]
Fix a bug where time-dependant generator variables could be forgotten during aggregation in a particular case. [#576]
A new type of
GlobalConstraint
called operational_limit is now supported through the Network.optimize function. It allows to limit the total production of a carrier analogous to primary_energy_limit with the difference that it applies directly to the production of a carrier rather than to an attribute of the primary energy use.Fix an issue appeared when processing networks which were reduced to a set of isolated nodes in course of clustering. Previously, an empty
Line
component has lead to problems when processing empty lines-related dataframes. That has been fixed by introducing special treatment in case a lines dataframe is empty. [#599]
v0.22.1 (15th February 2023)#
The model creation for large, sector-coupled models is now much quicker.
The FICO Xpress solver interface now skips loading a basis if there is an error associated with the basis function and continues without it.
The colors of borders and coastlines can now be controlled with
n.plot(color_geomap=dict(border='b', coastline='r'))
.Plotting multiple legends was fixed for applying a tight layout with
matplotlib>=3.6
.The plotting function now supports plotting negative and positive values separately per bus using the argument
`n.plot(bus_split_circles=...)
. This results in drawing separate half circles for positive and negative values.
v0.22.0 (3rd February 2023)#
Python 3.11 is now tested. The support of Python 3.7 was dropped. The minimum supported python version is now 3.8.
The linopy based optimization (
n.optimize()
) now allows to limit the carrier’s growth by an additional linear term, so that one can limit an expansion growth by multiples of what was installed in the preceding investment period.The linopy based optimization now requires
linopy
v0.1.1 or higher. The new version eases the creation of custom constraint through a better display of linear expression and variables.Wrapped functions defined by the
Network.optimize
accessor are now wrapping meta information of the original functions more coherently. This enables better feedback in interactive sessions.Checking of datatypes in the
consistency_check
is now deactivated by default. Setn.consistency_check(check_dtypes=True)
to activate it.The plotting functionality
n.plot()
now supports setting alpha values on the branch components individually.The plotting functionality
n.plot()
now allows independent control of arrow size and branch width usingline_widths
andflow
in conjunction.The documentation shines in a new look using the
sphinx-book-theme
. Limitsphinx
to versions below 6.Address various deprecation warnings.
v0.21.3 (16th December 2022)#
Bugfix: Time-varying marginal cost of a component were removed if at least one of its value was zero.
Bugfix: Due to xarray’s
groupby
operation not fully supporting multi-indexes in recent version (see pydata/xarray#6836), parts of the multi investment optimization code was adjusted.Update HiGHS parsing function in linopt for HiGHS version 1.4.0. Minimum version of HiGHS is v1.3.0. Older versions have not been tested.
Update of gas boiler example to
linopy
.New standard line types for DC lines.
Included code of conduct.
v0.21.2 (30th November 2022)#
Compatibility with
pyomo>=6.4.3
.
v0.21.1 (10th November 2022)#
Default of
n.lopf()
changed ton.lopf(pyomo=False)
.Bugfix in calculating statistics of curtailment.
Bugfix in IO of netCDF network files for datetime indices.
Bugfix for warning about imports from different PyPSA versions.
Add linopy and statistics module to API reference.
v0.21.0 (7th November 2022)#
A new optimization module optimization based on Linopy was introduced. It aims at being as fast as the in-house optimization code and as flexible as the optimization with
Pyomo
. A introduction to the optimization can be found at the examples section a migration guide for extra functionalities can be found at hereA new module for a quick calculation of system relevant quantities was introduced. It is directly accessible via the new accessor Network.statistics which returns a table of values often calculated manually. At the same time Network.statistics allows to call individual functions, as capex, opex, capacity_factor etc.
Add reference to Discord server for support and discussion.
Restore import of pandapower networks. Issues regarding the transformer component and indexing as well as missing imports for shunts are fixed. [#332]
The import performance of networks was improved. With the changes, the import time for standard netcdf imports decreased by roughly 70%.
v0.20.1 (6th October 2022)#
The representation of networks was modified to show the number of components and snapshots.
The performance of the consistency check function was improved. The consistency check was extended by validating the capacity expansion limits as well as global constraint attributes.
When applying network clustering algorithms, per unit time series are now aggregated using a capacity-weighted average and default aggregation strategies were adjusted.
The value of
n.objective
is now set to NaN for failed optimisation runs.Added example notebook on how to model redispatch with PyPSA.
Added new network plotting example.
Bugfix for non-pyomo version of
n.sclopf()
.Accept
pathlib.Path
objects when importing networks withpypsa.Network()
.Addressed
.iteritems()
deprecations.
v0.20.0 (26th July 2022)#
This release contains new features for plotting and storing metadata with Network objects.
A new attribute
n.meta
was added to the Network object. This can be an arbitrary dictionary, and is used to store meta data about the network.Improved support for individually normed colorbars in
n.plot()
for buses, lines, links, transformers with keyword argumentsbus_norm
,line_norm
,link_norm
,transformer_norm
.import pypsa import matplotlib.pyplot as plt n = pypsa.examples.ac_dc_meshed() norm = plt.Normalize(vmin=0, vmax=10) n.plot( bus_colors=n.buses.x, bus_cmap='viridis', bus_norm=norm ) plt.colorbar(plt.cm.ScalarMappable(cmap='viridis', norm=norm))
New utility functions to add legends for line widths (
pypsa.plot.add_legend_lines()
), circles and pie chart areas (pypsa.plot.add_legend_circles()
), and patch colors (pypsa.plot.add_legend_patches()
). See the following example:import pypsa import matplotlib.pyplot as plt import cartopy.crs as ccrs from pypsa.plot import add_legend_circles n = pypsa.examples.ac_dc_meshed() fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}) n.plot(ax=ax, bus_sizes=1) add_legend_circles( ax, [1, 0.5], ["reference size", "reference size 2"], legend_kw=dict(frameon=False, bbox_to_anchor=(1,0.1)) )
When iterating over components of a Subnetwork, only a those assets are included in the dataframes which are included in the subnetwork.
In
n.plot()
, compute boundaries in all cases for consistent circle sizes. This is realised by setting a new default margin of 0.05.Compatibility with pyomo 6.4.1.
Removed
pypsa.stats
module.Extended defaults for the clustering of attributes in
pypsa.networkclustering
.Removed deprecated clustering algorithms in
pypsa.networkclustering
.Improved documentation and README.
Fix a few deprecations.
Improved test coverage, e.g. when copying networks.
Testing:
pypower
is not importable with newest numpy versions. Skip test if import fails.
Special thanks for this release to @Cellophil, @txelldm and @rockstaedt for improving test coverage and documentation.
v0.19.3 (22nd April 2022)#
Apply pre-commit formats to support development (incl. black formatting, jupyter cleanup, import sorting, preventing large file uploads). This will distort
git blame
functionality, which can be fixed by runninggit config blame.ignoreRevsFile .git-blame-ignore-revs
inside the PyPSA repository. Runpre-commit install
to set up locally.Change message when exporting and importing networks without a set
network_name
. Fixes [#381].Greedy Modularity Maximisation was introduced as new spatial clustering method [#377].
v0.19.2 (7th March 2022)#
Add standard line type for 750 kV transmission line.
v0.19.1 (18th February 2022)#
When setting ramp limits for links and calling
Network.lopf
withpyomo=False
, an unexpected KeyError was raised. This was fixed by correctly accessing the data frame referring to the power dispatch of links.
v0.19.0 (11th February 2022)#
This release contains new features for ramping constraints in link components, hierarchical network clustering functionality, and an interface to the open-source HiGHS solver.
New Features
Ramp limits for
Links
. TheLink
component has two new attributes,ramp_limit_up
andramp_limit_down
, which limits the marginal power increase equivalent to the implementation for generators. The new attributes are only considered when runningnetwork.lopf(pyomo=False)
.Hierarchical Agglomerative Clustering (HAC) was introduced as new spatial clustering method [#289].
Clustering networks now also supports the clustering of time-series associated to lines.
Add open-source HiGHS solver.
A new convenience function
Network.get_committable_i
was added. This returns an index containing all committable assets of componentc
. In case that componentc
does not support committable assets, it returns an empty dataframe.A warning message is shown if a network contains one or more links with an
efficiency
smaller than 1 and a negative value forp_min_pu
[#320].New example for spatial clustering.
Speed-up of
network.plot()
by only plotting buses with non-zero size.Increased test coverage.
Changes
The names of the indexes in static dataframes are now set to the component names. So, the index of
n.generators
has the name ‘Generator’. The same accounts for the columns of the timeseries.The snapshot levels of a multi-indexed snapshot were renamed to [‘period’, ‘timestep’], the name of the index was set to ‘snapshot’. This makes the snapshot name coherent for single and multi-indexed snapshots.
Bugs and Compatibility
Compatibility with
pandas>=1.4
.Drop support for Python 3.6 in accordance with its [end-of-life](https://endoflife.date/python).
Use
nx.Graph
instead ofnx.OrderedGraph
which guarantees order is preserved for Python 3.7 and above.Add assert: CBC solver does not work with ‘>’ and ‘<’.
When running
network.lopf(pyomo=False)
, the ramp limits did not take the time step right before the optimization horizon into account (relevant for rolling horizon optimization). This is now fixed.Fix bug when multi-links are defined but the network has no links.
Special thanks for this release to Samuel Matthew Dumlao (@smdumlao) for implementing the ramp limits for Links in PyPSA, Martha Frysztacki (@martacki) for implementing the hierarchical network clustering, and Max Parzen (@pz-max) for implementing the HiGHS solver interface.
v0.18.1 (15th October 2021)#
Compatibility with
pyomo>=6.1
.Bugfix: specifying the
solver_logfile
is no longer mandatory with CPLEX forn.lopf(pyomo=False)
.The distance measures for the network clustering functions
busmap_by_spectral()
andbusmap_by_louvain()
were adapted to use electrical distance (s_nom/|r+i*x|
) (before:num_parallel
).Deprecations: The functions
busmap_by_linemask()
,busmap_by_length()
,length_clustering()
,busmap_by_spectral_clustering()
,spectral_clustering()
,busmap_by_louvain()
,louvain_clustering()
,busmap_by_rectangular_grid()
,rectangular_grid_clustering()
andstubs_clustering()
were deprecated and will be removed in v0.20.Distance measures for function
busmap_by_spectral()
andbusmap_by_louvain()
were adapted to electrical distance (s_nom/|r+i*x|
) (before:num_parallel
)In
pypsa.networkclustering
, strip the string of the clustered component name. Not doing this had caused troubles for components with an empty carrier column.Various documentation updates.
v0.18.0 (12th August 2021)#
This release contains new features for pathway optimisation, improvements of the documentation’s examples section as well as compatibility and bug fixes.
Licensing
With this release, we have changed the licence from the copyleft GPLv3 to the more liberal MIT licence with the consent of all contributors (for the reasoning why, see #274).
New features
Added support for the optimisation of multiple investment periods, also known as pathway optimization. With this feature, snapshots can span over multiple years or decades which are divided into investment periods. Within each investment period, assets can be added to the network. The optimization only works with
pyomo=False
. For more information see the documentation at Multiple investment periods and the example notebook. Endogenous learning curves can be applied asextra_functionality
.n.snapshot_weightings
is now apandas.DataFrame
rather than apandas.Series
with weightings now subdivided into weightings for the objective function, generators and stores/storage units. This separation of weightings is relevant for temporal snapshot clustering, where the weight in the objective function may differ from the number of hours represented by each snapshot for storage purposes.Objective weightings determine the multiplier of the marginal costs in the objective function of the LOPF.
Generator weightings specify the impact of generators in a
GlobalConstraint
(e.g. in a carbon dioxide emission constraint).Store weightings define the elapsed hours for the charge, discharge, standing loss and spillage of storage units and stores in order to determine the current state of charge.
PyPSA still supports setting
n.snapshot_weightings
with apandas.Series
. In this case, the weightings are uniformly applied to all columns of the newn.snapshot_weightings
pandas.DataFrame
.All functionalities except for optimisation with
pyomo=True
now work with multi-indexed snapshots.Many example notebooks are now also integrated in the documentation. See Quick Start, Power System Optimization, Sector Coupling and Other Examples.
A new module
examples
was added which contains frontend functions for retrieving/loading example networks provided by the PyPSA project.When solving
n.lopf(pyomo=False)
, PyPSA now supports setting lower and upper capacity bounds per bus and carrier. These are specified in the columnsn.buses['nom_min_{carrier}']
andn.buses['nom_max_{carrier}']
respectively. For example, if multiple generators of carrierwind
are at busbus1
, the combined capacity is limited to 1000 MW by settingn.buses.loc['bus1', 'nom_max_wind'] = 1000
(a minimal capacity is forced by settingn.buses.loc['bus1', 'nom_min_wind']
). In the same manner the combinedp_nom
of componentsStorageUnit
ande_nom
of componentsStore
can be limited.Add new attribute
carrier
to the componentsLine
,Link
,Store
andLoad
, defining the energy carrier of the components. Its default is an empty string. When callingn.calculate_dependent_values()
, empty carriers are replaced by the carriers of the buses to which the components are attached.Add new descriptive attribute
unit
tobus
component.Automated upload of code coverage reports for pull requests.
Changes
When using iterative LOPF with
n.ilopf()
to consider impedance updates of reinforced transmission lines, the attributesp_nom
ands_nom
of lines and links are reset to their original values after final iteration.n.snapshots
are now a property, hence assigning values withn.snapshots = values
is the same asn.set_snapshots(values)
.Remove deprecated function
geo.area_from_lon_lat_poly
.
Deprecations
The function
geo.area_from_lon_lat_poly()
was deprecated and will be removed in v0.19.The deprecated argument
csv_folder_name
inpypsa.Network
was removed.The deprecated column names
source
,dispatch
,p_max_pu_fixed
,p_min_pu_fixed
for the classGenerator
,current_type
for the classBus
ands_nom
for the classLink
were removed.
Bugs and Compatibility
Added support for
pandas
version 1.3.Adjust log file creation for CPLEX version 12.10 and higher.
n.snapshot_weightings
is no longer copied forn.copy(with_time=False)
.Bugfix in
n.ilopf()
where previously all links were fixed in the final iteration when it should only be the HVDC links.Fix setting
margin
andboundaries
when plotting a network withgeomap=False
.
Special thanks for this release to Lisa Zeyen (@lisazeyen) for implementing the multi-horizon investment in PyPSA and to Fabian Hofmann (@FabianHofmann) for thoroughly reviewing it and adding the example notebooks to the documentation.
v0.17.1 (15th July 2020)#
This release contains bug fixes and extensions to the features for optimization when not using Pyomo.
N-1 security-constrained linear optimal power flow is now also supported without pyomo by running
network.sclopf(pyomo=False)
.Added support for the FICO Xpress commercial solver for optimization without pyomo, i.e.
pyomo=False
.There was a bug in the LOPF with
pyomo=False
whereby if some Links were defined with multiple outputs (i.e. bus2, bus3, etc. were defined), but there remained some Links without multiple outputs (bus2, bus3, etc. set to""
), then the Links without multiple outputs were assigned erroneous non-zero values for p2, p3, etc. in the LOPF withpyomo=False
. Now p2, p3, etc. revert to the default value for Links where bus2, bus3, etc. are not defined, just like for the LOPF withpyomo=True
.Handle double-asterisk prefix in
solution_fn
when solvingn.lopf(pyomo=False)
using CBC.When solving
n.lopf(pyomo=False, store_basis=True, solver_name="cplex")
an error raised by trying to store a non-existing basis is caught.Add compatibility for Pyomo 5.7. This is also the new minimum requirement.
Fixed bug when saving dual variables of the line volume limit. Now using dual from the second last iteration in
pypsa.linopf
, because last iteration returns NaN (no optimisation of line capacities in final iteration).Added tracking of iterations of global constraints in the optimisation.
When solving
n.lopf(pyomo=False)
, PyPSA now constrains the dispatch variables for non extendable components with actual constraints, not with standard variable bounds. This allows retrieving shadow prices for all dispatch variables when runningn.lopf(pyomo=False, keep_shadowprices=True)
.Can now cluster lines with different static
s_max_pu
values. Time-varyings_max_pu
are not supported in clustering.Improved handling of optional dependencies for network clustering functionalities (
sklearn
andcommunity
).
Thanks to Pietro Belotti from FICO for adding the Xpress support, to Fabian Neumann (KIT) and Fabian Hofmann (FIAS) for all their hard work on this release, and to all those who fixed bugs and reported issues.
v0.17.0 (23rd March 2020)#
This release contains some minor breaking changes to plotting, some new features and bug fixes.
For plotting geographical features
basemap
is not supported anymore. Please usecartopy
instead.Changes in the plotting functions
n.plot()
andn.iplot()
include some breaking changes:A set of new arguments were introduced to separate style parameters of the different branch components:
link_colors
,link_widths
,transformer_colors
,transformer_widths
,link_cmap
,transformer_cmap
line_widths
,line_colors
, andline_cmap
now only apply for lines and can no longer be used for other branch types (links and transformers). Passing a pandas.Series with a pandas.MultiIndex will raise an error.Additionally, the function n.iplot() has new arguments
line_text
,link_text
,transformer_text
to configure the text displayed when hovering over a branch component.The function
directed_flow()
now takes only a pandas.Series with single pandas.Index.The argument
bus_colorscale
inn.iplot()
was renamed tobus_cmap
.The default colours changed.
If non-standard output fields in the time-dependent
network.components_t
(e.g.network.links_t.p2
when there are multi-links) were exported, then PyPSA will now also import them automatically without requiring the use of theoverride_component_attrs
argument.Deep copies of networks can now be created with a subset of snapshots, e.g.
network.copy(snapshots=network.snapshots[:2])
.When using the
pyomo=False
formulation of the LOPF (network.lopf(pyomo=False)
):It is now possible to alter the objective function. Terms can be added to the objective via
extra_functionality
using the function pypsa.linopt.write_objective. When a pure custom objective function needs to be declared, one can setskip_objective=True
. In this case, only terms defined throughextra_functionality
will be considered in the objective function.Shadow prices of capacity bounds for non-extendable passive branches are parsed (similar to the
pyomo=True
setting)Fixed pypsa.linopf.define_kirchhoff_constraints to handle exclusively radial network topologies.
CPLEX is now supported as an additional solver option. Enable it by installing the cplex package (e.g. via
pip install cplex
orconda install -c ibmdecisionoptimization cplex
) and settingsolver_name='cplex'
When plotting,
bus_sizes
are now consistent when they have apandas.MultiIndex
or apandas.Index
. The default is changed tobus_sizes=0.01
because the bus sizes now relate to the axis values.When plotting,
bus_alpha
can now be used to add an alpha channel which controls the opacity of the bus markers.The argument
bus_colors
can a now also be a pandas.Series.The
carrier
component has two new columns ‘color’ and ‘nice_name’. The color column is used by the plotting function ifbus_sizes
is a pandas.Series with a MultiIndex andbus_colors
is not explicitly defined.The function pypsa.linopf.ilopf can now track the intermediate branch capacities and objective values for each iteration using the
track_iterations
keyword.Fixed unit commitment:
when
min_up_time
of committable generators exceeds the length of snapshots.when network does not feature any extendable generators.
Fixed import from pandapower for transformers not based on standard types.
The various Jupyter Notebook examples are now available on the binder platform. This allows new users to interactively run and explore the examples without the need of installing anything on their computers.
Minor adjustments for compatibility with pandas v1.0.0.
After optimizing, the network has now an additional attribute
objective_constant
which reflects the capital cost of already existing infrastructure in the network referring top_nom
ands_nom
values.
Thanks to Fabian Hofmann (FIAS) and Fabian Neumann (KIT) for all their hard work on this release, and to all those who reported issues.
v0.16.1 (10th January 2020)#
This release contains a few minor bux fixes from the introduction of nomopyomo in the previous release, as well as a few minor features.
When using the
nomopyomo
formulation of the LOPF withnetwork.lopf(pyomo=False)
, PyPSA was not correcting the bus marginal prices by dividing by thenetwork.snapshot_weightings
, as is done in thepyomo
formulation. This correction is now applied in thenomopyomo
formulation to be consistent with thepyomo
formulation. (The reason this correction is applied is so that the prices have a clear currency/MWh definition regardless of the snapshot weightings. It also makes them stay roughly the same when snapshots are aggregated: e.g. if hourly simulations are sampled every n-hours, and the snapshot weighting is n.)The
status, termination_condition
that thenetwork.lopf
returns is now consistent between thenomopyomo
andpyomo
formulations. The possible return values are documented in the LOPF docstring, see also the LOPF documentation. Furthermore in thenomopyomo
formulation, the solution is still returned when gurobi finds a suboptimal solution, since this solution is usually close to optimal. In this case the LOPF returns astatus
ofwarning
and atermination_condition
ofsuboptimal
.For plotting with
network.plot()
you can override the bus coordinates by passing it alayouter
function fromnetworkx
. See the docstring for more information. This is particularly useful for networks with no defined coordinates.For plotting with
network.iplot()
a background from mapbox can now be integrated.
Please note that we are still aware of one implementation difference
between nomopyomo
and pyomo
, namely that nomopyomo
doesn’t read
out shadow prices for non-extendable branches, see the github issue.
v0.16.0 (20th December 2019)#
This release contains major new features. It is also the first release to drop support for Python 2.7. Only Python 3.6 and 3.7 are supported going forward. Python 3.8 will be supported as soon as the gurobipy package in conda is updated.
A new version of the linear optimal power flow (LOPF) has been introduced that uses a custom optimization framework rather than Pyomo. The new framework, based on nomoypomo, uses barely any memory and is much faster than Pyomo. As a result the total memory usage of PyPSA processing and gurobi is less than a third what it is with Pyomo for large problems with millions of variables that take several gigabytes of memory (see this graphical comparison for a large network optimization). The new framework is not enabled by default. To enable it, use
network.lopf(pyomo=False)
. Almost all features of the regularnetwork.lopf
are implemented with the exception of minimum down/up time and start up/shut down costs for unit commitment. If you use theextra_functionality
argument fornetwork.lopf
you will need to update your code for the new syntax. There is documentation for the new syntax as well as a Jupyter notebook of examples.Distributed active power slack is now implemented for the full non-linear power flow. If you pass
network.pf()
the argumentdistribute_slack=True
, it will distribute the slack power across generators proportional to generator dispatch by default, or according to the distribution scheme provided in the argumentslack_weights
. Ifdistribute_slack=False
only the slack generator takes up the slack. There is further documentation.Unit testing is now performed on all of GNU/Linux, Windows and MacOS.
NB: You may need to update your version of the package
six
.
Special thanks for this release to Fabian Hofmann for implementing the nomopyomo framework in PyPSA and Fabian Neumann for providing the customizable distributed slack.
v0.15.0 (8th November 2019)#
This release contains new improvements and bug fixes.
The unit commitment (UC) has been revamped to take account of constraints at the beginning and end of the simulated
snapshots
better. This is particularly useful for rolling horizon UC. UC now accounts for up-time and down-time in the periods before thesnapshots
. The generator attributeinitial_status
has been replaced with two attributesup_time_before
anddown_time_before
to give information about the status beforenetwork.snapshots
. At the end of the simulatedsnapshots
, minimum up-times and down-times are also enforced. Ramping constraints also look before the simulation at previous results, if there are any. See the unit commitment documentation for full details. The UC example has been updated with a rolling horizon example at the end.Documentation is now available on readthedocs, with information about functions pulled from the docstrings.
The dependency on cartopy is now an optional extra.
PyPSA now works with pandas 0.25 and above, and networkx above 2.3.
A bug was fixed that broke the Security-Constrained Linear Optimal Power Flow (SCLOPF) constraints with extendable lines.
Network plotting can now plot arrows to indicate the direction of flow by passing
network.plot
anflow
argument.The objective sense (
minimize
ormaximize
) can now be set (default remainsminimize
).The
network.snapshot_weightings
is now carried over when the network is clustered.Various other minor fixes.
We thank colleagues at TERI for assisting with testing the new unit commitment code, Clara Büttner for finding the SCLOPF bug, and all others who contributed issues and pull requests.
v0.14.1 (27th May 2019)#
This minor release contains three small bug fixes:
Documentation parses now correctly on PyPI
Python 2.7 and 3.6 are automatically tested using Travis
PyPSA on Python 2.7 was fixed
This will also be the first release to be available directly from conda-forge.
v0.14.0 (15th May 2019)#
This release contains a new feature and bug fixes.
Network plotting can now use the mapping library cartopy as well as basemap, which was used in previous versions of PyPSA. The basemap developers will be phasing out basemap over the next few years in favour of cartopy (see their end-of-life announcement). PyPSA now defaults to cartopy unless you tell it explicitly to use basemap. Otherwise the plotting interface is the same as in previous versions.
Optimisation now works with the newest version of Pyomo 5.6.2 (there was a Pyomo update that affected the opt.py expression for building linear sums).
A critical bug in the networkclustering sub-library has been fixed which was preventing the capital_cost parameter of conventional generators being handled correctly when networks are aggregated.
Network.consistency_check() now only prints necessary columns when reporting NaN values.
Import from pandapower networks has been updated to pandapower 2.0 and to include non-standard lines and transformers.
We thank Fons van der Plas and Fabian Hofmann for helping with the cartopy interface, Chloe Syranidis for pointing out the problem with the Pyomo 5.6.2 update, Hailiang Liu for the consistency check update and Christian Brosig for the pandapower updates.
v0.13.2 (10th January 2019)#
This minor release contains small new features and fixes.
Optimisation now works with Pyomo >= 5.6 (there was a Pyomo update that affected the opt.py LConstraint object).
New functional argument can be passed to Network.lopf: extra_postprocessing(network,snapshots,duals), which is called after solving and results are extracted. It can be used to get the values of shadow prices for constraints that are not normally extracted by PyPSA.
In the lopf kirchhoff formulation, the cycle constraint is rescaled by a factor 1e5, which improves the numerical stability of the interior point algorithm (since the coefficients in the constraint matrix were very small).
Updates and fixes to networkclustering, io, plot.
We thank Soner Candas of TUM for reporting the problem with the most recent version of Pyomo and providing the fix.
v0.13.1 (27th March 2018)#
This release contains bug fixes for the new features introduced in 0.13.0.
Export network to netCDF file bug fixed (components that were all standard except their name were ignored).
Import/export network to HDF5 file bug fixed and now works with more than 1000 columns; HDF5 format is no longer deprecated.
When networks are copied or sliced, overridden components (introduced in 0.13.0) are also copied.
Sundry other small fixes.
We thank Tim Kittel for pointing out the first and second bugs. We thank Kostas Syranidis for not only pointing out the third issue with copying overridden components, but also submitting a fix as a pull request.
For this release we acknowledge funding to Tom Brown from the RE-INVEST project.
v0.13.0 (25th January 2018)#
This release contains new features aimed at coupling power networks to other energy sectors, fixes for library dependencies and some minor internal API changes.
If you want to define your own components and override the standard functionality of PyPSA, you can now override the standard components by passing pypsa.Network() the arguments
override_components
andoverride_component_attrs
, see the section on Custom Components. There are examples for defining new components in the git repository inexamples/new_components/
, including an example of overridingnetwork.lopf()
for functionality for combined-heat-and-power (CHP) plants.The
Link
component can now be defined with multiple outputs in fixed ratio to the power in the single input by defining new columnsbus2
,bus3
, etc. (bus
followed by an integer) innetwork.links
along with associated columns for the efficienciesefficiency2
,efficiency3
, etc. The different outputs are then proportional to the input according to the efficiency; see sections Multilink and Link constraints and the example of a CHP with a fixed power-heat ratio.Networks can now be exported to and imported from netCDF files with
network.export_to_netcdf()
andnetwork.import_from_netcdf()
. This is faster than using CSV files and the files take up less space. Import and export with HDF5 files, introduced in v0.12.0, is now deprecated.The export and import code has been refactored to be more general and abstract. This does not affect the API.
The internally-used sets such as
pypsa.components.all_components
andpypsa.components.one_port_components
have been moved frompypsa.components
tonetwork
, i.e.network.all_components
andnetwork.one_port_components
, since these sets may change from network to network.For linear power flow, PyPSA now pre-calculates the effective per unit reactance
x_pu_eff
for AC lines to take account of the transformer tap ratio, rather than doing it on the fly; this makes some code faster, particularly the kirchhoff formulation of the LOPF.PyPSA is now compatible with networkx 2.0 and 2.1.
PyPSA now requires Pyomo version greater than 5.3.
PyPSA now uses the Travis CI continuous integration service to test every commit in the PyPSA GitHub repository. This will allow us to catch library dependency issues faster.
We thank Russell Smith of Edison Energy for the pull request for the effective reactance that sped up the LOPF code and Tom Edwards for pointing out the Pyomo version dependency issue.
For this release we also acknowledge funding to Tom Brown from the RE-INVEST project.
v0.12.0 (30th November 2017)#
This release contains new features and bug fixes.
Support for Pyomo’s persistent solver interface, so if you’re making small changes to an optimisation model (e.g. tweaking a parameter), you don’t have to rebuild the model every time. To enable this,
network_lopf
has been internally split intobuild_model
,prepare_solver
andsolve
to allow more fine-grained control of the solving steps. Currently the new Pyomo PersistentSolver interface is not in the main Pyomo branch, see #223; you can obtain it withpip install git+https://github.com/Pyomo/pyomo@persistent_interfaces
Lines and transformers (i.e. passive branches) have a new attribute
s_max_pu
to restrict the flow in the OPF, just likep_max_pu
for generators and links. It works by restricting the absolute value of the flow per unit of the nominal ratingabs(flow) <= s_max_pu*s_nom
. For lines this can represent an n-1 contingency factor or it can be time-varying to represent weather-dependent dynamic line rating.The
marginal_cost
attribute of generators, storage units, stores and links can now be time dependent.When initialising the Network object, i.e.
network = pypsa.Network()
, the first keyword argument is nowimport_name
instead ofcsv_folder_name
. Withimport_name
PyPSA recognises whether it is a CSV folder or an HDF5 file based on the file name ending and deals with it appropriately. Example usage:nw1 = pypsa.Network("my_store.h5")
andnw2 = pypsa.Network("/my/folder")
. The keyword argumentcsv_folder_name
is still there but is deprecated.The value
network.objective
is now read from the Pyomo results attributeUpper Bound
instead ofLower Bound
. This is because for MILP problems under certain circumstances CPLEX records theLower bound
as the relaxed value.Upper bound
is correctly recorded as the integer objective value.Bug fix due to changes in pandas 0.21.0: A bug affecting various places in the code, including causing
network.lopf
to fail with GLPK, is fixed. This is because in pandas 0.21.0 the sum of an empty Series/DataFrame returns NaN, whereas before it returned zero. This is a subtle bug; we hope we’ve fixed all instances of it, but get in touch if you notice NaNs creeping in where they shouldn’t be. All our tests run fine.Bug fix due to changes in scipy 1.0.0: For the new version of scipy,
csgraph
has to be imported explicit.Bug fix: A bug whereby logging level was not always correctly being seen by the OPF results printout is fixed.
Bug fix: The storage unit spillage had a bug in the LOPF, whereby it was not respecting
network.snapshot_weightings
properly.
We thank René Garcia Rosas, João Gorenstein Dedecca, Marko Kolenc, Matteo De Felice and Florian Kühnlenz for promptly notifying us about issues.
v0.11.0 (21st October 2017)#
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 (sparse) documentation Plotting Networks.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.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.
v0.10.0 (7th August 2017)#
This release contains some minor new features and a few minor but important API changes.
There is a new component Global Constraints for implementing constraints that effect many components at once (see also the LOPF subsection Global constraints). 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 Energy flow balances.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()
.
v0.9.0 (29th April 2017)#
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 Unit commitment constraints 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 Ramping constraints and the unit commitment example.
Different mathematically-equivalent formulations for the Linear Optimal Power Flow (LOPF) are now documented 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 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.
v0.8.0 (25th January 2017)#
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 Line Types. For transformers you just need to specify the type, see 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 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 Components, so the documentation will always be up-to-date.All examples have been updated appropriately.
v0.7.1 (26th November 2016)#
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.
v0.7.0 (20th November 2016)#
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 Time-varying data 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 Troubleshooting.
All examples have been updated to accommodate the changes listed below.
v0.6.2 (4th November 2016)#
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.
v0.6.1 (25th August 2016)#
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.
v0.6.0 (23rd August 2016)#
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.
Sector coupling
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.
Downgrading object interface
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.
Other
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.
v0.5.0 (21st July 2016)#
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 Time-varying data), which will be implemented in the next major release v0.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
https://pypsa.readthedocs.io/en/latest/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 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 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.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.
v0.4.2 (17th June 2016)#
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.
v0.4.1 (3rd April 2016)#
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.
v0.4.0 (21st March 2016)#
Additional features:
New module
pypsa.contingency
for contingency analysis and security-constrained LOPFNew 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.
v0.3.3 (29th February 2016)#
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.
v0.3.2 (17th February 2016)#
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)
.
v0.3.1 (7th February 2016)#
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.
v0.3.0 (27th January 2016)#
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.
Release process#
Update
doc/references/release-notes.rst
You don’t need to update the version number anywhere, this is done automatically.
git commit
and put release notes in commit messagegit tag vx.x.x
git push
andgit push --tags
The upload to PyPI is automated in the Github Action
deploy.yml
, which is triggered by pushing a tag. To upload manually, runpython setup.py sdist
, thentwine check dist/pypsa-0.x.0.tar.gz
andtwine upload dist/pypsa-0.x.0.tar.gz
The GitHub release is also automated in the Github Action. Making a GitHub release will also trigger zenodo to archive the release with its own DOI.
To update to conda-forge, check the pull request generated at the feedstock repository.
Inform the PyPSA mailing list.