Skip to content

Commit

Permalink
Merge branch 'load_types_zip_coefficents' of https://github.com/mfisc…
Browse files Browse the repository at this point in the history
…h42/pandapower into load_types_zip_coefficents

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
  • Loading branch information
mfisch42 committed Dec 12, 2024
2 parents b32e72a + dd66fb0 commit 2d2aeae
Show file tree
Hide file tree
Showing 69 changed files with 9,671 additions and 1,041 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/github_test_action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,8 @@ jobs:
- name: Check docs for Python ${{ matrix.python-version }}
uses: e2nIEE/sphinx-action@master
with:
pre-build-command: "python -m pip install --upgrade pip;
python -m pip install .[docs];"
pre-build-command: "apt update && apt upgrade -y && apt install -y build-essential gfortran cmake pkg-config libopenblas-dev;
python -m pip install --upgrade pip;
python -m pip install .[docs];"
build-command: "sphinx-build -b html . _build -W"
docs-folder: "doc/"
3 changes: 1 addition & 2 deletions .install_julia.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ case $(uname) in
curl -L "$BASEURL/linux/$ARCH/$JULIANAME-$SUFFIX.tar.gz" | tar -xz
sudo ln -s $PWD/julia-*/bin/julia /usr/local/bin/julia
julia -e 'import Pkg; Pkg.add("PyCall");'
julia -e 'import Pkg; Pkg.add("PowerModels"); Pkg.add("Ipopt");'
julia -e 'import Pkg; Pkg.add("JSON"); Pkg.add("JuMP"); Pkg.add("Cbc"); Pkg.add("Juniper");'
julia -e 'import Pkg; Pkg.Registry.update(); Pkg.add("PandaModels"); Pkg.build(); Pkg.resolve();'
;;
Darwin)
if [ -e /usr/local/bin/julia ]; then
Expand Down
21 changes: 20 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Change Log
=============

[upcoming release] - 2024-..-..
-------------------------------
- [ADDED] pandas series accessor for geo column
- [FIXED] Increasing geojson precision as the default precision might cause problems with pandahub
- [ADDED] Add GeographicalRegion and SubGeographicalRegion names and ids to bus df in cim converter
- [CHANGED] Capitalize first letter of columns busbar_id, busbar_name and substation_id in bus df for cim converter
- [FIXED] Do not modify pandas options when importing pandapower
- [ADDED] improved lightsim2grid documentation including compatibitliy issues
- [FIXED] cim2pp: set default xml encoding to None to avoid error after changing to lxml

[2.14.11] - 2024-07-08
-------------------------------
- [FIXED] Lightsim2grid version
Expand All @@ -16,7 +26,12 @@ Change Log
[upcoming release] - 2024-..-..
-------------------------------

- [ADDED] pf2pp: possibility to convert a specific varaint and scenario
- [FIXED] PandaModels OPF with 'bus_dc' key errors
- [FIXED] julia tests
- [FIXED] copy array element to standard python scalar
- [FIXED] passing literal json to 'read_json' is deprecated
- [FIXED] replacing deprecated in1d with isin
- [ADDED] A switch to disable updating the vk and vkr values for trafo3w
- [FIXED] cast the column to the correct type before assigning values
- [FIXED] replacement for deprecated namespaces scipy.sparse.csc and scipy.sparse.csr
- [FIXED] copy array element to standard python scalar
Expand Down Expand Up @@ -81,7 +96,11 @@ Change Log
- [ADDED] Add VSC element, dc buses, dc lines, and hybrid AC/DC power flow calculation
- [CHANGED] accelerate _integrate_power_elements_connected_with_switch_buses() in get_equivalent()
- [CHANGED] accelerate distributed slack power flow calculation by using sparse-aware operations in _subnetworks()
- [CHANGED] Trafo Controllers can now be added to elements that are out of service, changed self.nothing_to_do()
- [ADDED] Discrete shunt controller for local voltage regulation with shunt steps
- [ADDED] fix lengths missmatch of output if ignore_zero_length is False in plotting utility function coords_from_node_geodata() and rename ignore_zero_length by ignore_no_geo_diff
- [ADDED] cim2pp converter: Using lxml to parse XML files (better performance)
- [ADDED] possibility to load JSON files with unknown object models and just store the models as dictionaries in the network

[2.14.7] - 2024-06-14
-------------------------------
Expand Down
65 changes: 61 additions & 4 deletions doc/powerflow/ac.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,69 @@ pandapower uses PYPOWER to solve the power flow problem:
If you are interested in the pypower casefile that pandapower is using for power flow, you can find it in net["_ppc"].
However all necessary informations are written into the pandpower format net, so the pandapower user should not usually have to deal with pypower.

If available, the librabry lightsim2grid is used as a backend for power flow simulation instead of the
implementation in pandapower, leading to a boost in performance. The library lightsim2grid is implemented in C++ and
can either be installed with pip install lightsim2grid, or built from source. More about the library and the
installation guide can be found in the `documentation <https://lightsim2grid.readthedocs.io/en/latest/>`_ or
Accelerating Packages
-------------------------

Two external packages are available which let accelerate pandapower's power flow command :code:`runppp`:

1. numba
2. lightsim2grid

If available, i.e. installed on the operating computer, the code will check by default all
prerequisites to use the external packages. numba is a python JIT compiler,
cf. `link <https://pypi.org/project/numba/>`_. In constrast, the library lightsim2grid
is used as a backend for power flow simulation instead of the
implementation in pandapower. It leads to a boost in performance. The library lightsim2grid is
implemented in C++ and can either be installed with pip install lightsim2grid, or built from source.
More about the library and the installation guide can be found in the
`documentation <https://lightsim2grid.readthedocs.io/en/latest/>`_ or
its GitHub `repository <https://github.com/BDonnot/lightsim2grid>`_.

lightsim2grid Compatibility
```````````````````````````````

lightsim2grid is supported if all the following conditions are met:

1. The lightsim2grid library is installed and available.
2. The selected power flow algorithm is Newton-Raphson (algorithm='nr').
3. Voltage-dependent loads are not enabled (voltage_depend_loads=False).
4. Either:

* There is only one slack bus in the network, or
* Distributed slack is enabled (distributed_slack=True).

5. None of the following elements are present in the grid model:

* Controllable shunts, including SVC, SSC, or VSC elements.
* Controllable impedances, such as TCSC elements.
* DC elements, including DC buses (bus_dc) or DC lines (line_dc).

6. Temperature-Dependent Power Flow is not requested (tdpf=False).

When lightsim2grid is Not Supported
```````````````````````````````````````

If any of the above conditions are not met, lightsim2grid cannot be used. In such cases:

* If lightsim2grid='auto' (default), the fallback to the standard pandapower implementation occurs without a detailed message.
* If lightsim2grid=True is explicitly set, an appropriate error or warning is raised or logged, depending on the condition.

Common Limitations of lightsim2grid
````````````````````````````````````````

lightsim2grid does not currently support:

* Algorithms other than Newton-Raphson
* Voltage-dependent loads
* Multiple slack buses without distributed slack
* Grids containing any of the following advanced elements:

* Controllable shunts (SVC, SSC, VSC)
* Controllable impedances (TCSC)
* DC buses or DC lines

* Temperature-Dependent Power Flow (tdpf=True)

Temperature-Dependent Power Flow (TDPF)
---------------------------------------

Expand Down
3 changes: 3 additions & 0 deletions pandapower/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
from pandapower.runpm import *
from pandapower.pf.runpp_3ph import runpp_3ph

import geojson
geojson.geometry.DEFAULT_PRECISION = 8

import pandas as pd
pd.options.mode.chained_assignment = None # default='warn'

Expand Down
95 changes: 92 additions & 3 deletions pandapower/auxiliary.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from importlib.metadata import PackageNotFoundError
from typing_extensions import deprecated

from geojson import loads, GeoJSON
import numpy as np
import pandas as pd
import scipy as sp
Expand All @@ -58,9 +59,16 @@
import pandaplan.core.pplog as logging
except ImportError:
import logging
try:
from geopandas import GeoSeries
from shapely import from_geojson
geopandas_available = True
except ImportError:
geopandas_available = False

logger = logging.getLogger(__name__)


def log_to_level(msg, passed_logger, level):
if level == "error":
passed_logger.error(msg)
Expand Down Expand Up @@ -343,6 +351,85 @@ def __repr__(self): # pragma: no cover
return "\n".join(lines)


@pd.api.extensions.register_series_accessor("geojson")
class GeoAccessor:
"""
pandas Series accessor for the geo column. It facilitates the use of geojson strings.
NaN entrys are dropped using the accessor!
"""
def __init__(self, pandas_obj):
self._validate(pandas_obj)
self._obj = pandas_obj

@staticmethod
def _validate(obj):
try:
if not obj.dropna().apply(loads).apply(isinstance, args=(GeoJSON,)).all():
raise AttributeError("Can only use .geojson accessor with geojson string values!")
except Exception as e:
raise AttributeError(f"Can only use .geojson accessor with geojson string values!: {e}")
if not geopandas_available:
soft_dependency_error("GeoAccessor", "geopandas")

@staticmethod
def _extract_coords(x):
if x["type"] == "Point":
return np.array(x["coordinates"])
return [np.array(y) for y in x["coordinates"]]

@property
def _coords(self):
"""
Extracts the geometry coordinates from the GeoJSON strings.
It is not recommended to use the standalone coordinates.
Important informations like the crs or latlon/lonlat are lost as a result.
"""
return self._obj.dropna().apply(loads).apply(self._extract_coords)

@property
def as_geo_obj(self):
"""
Loads the GeoJSON objects.
"""
return self._obj.dropna().apply(loads)

@property
def type(self):
"""
Extracts the geometry type of the GeoJSON string.
"""
return self._obj.dropna().apply(loads).apply(lambda x: str(x["type"]))

@property
def as_shapely_obj(self):
"""
Converts the GeoJSON strings to shapely geometrys.
"""
return self._obj.dropna().apply(from_geojson)

@property
def as_geoseries(self):
"""
Converts the PandasSeries to a GeoSeries with shapely geometrys.
"""
return GeoSeries(self._obj.dropna().pipe(from_geojson), crs=4326, index=self._obj.dropna().index)

def __getattr__(self, item):
"""
Enables access to all methods or attribute calls from a GeoSeries.
"""
geoms = self.as_geoseries
if hasattr(geoms, item):
geoms_item = getattr(geoms, item)
if callable(geoms_item):
def wrapper(*args, **kwargs):
return geoms_item(*args, **kwargs)
return wrapper
else:
return geoms_item
raise AttributeError(f"'GeoAccessor' object has no attribute '{item}'")


def plural_s(number):
return "" if number == 1 else "s"

Expand Down Expand Up @@ -1186,9 +1273,11 @@ def _check_if_numba_is_installed(level="warning"):

def _check_lightsim2grid_compatibility(net, lightsim2grid, voltage_depend_loads, algorithm, distributed_slack, tdpf):
"""
Implement some checks to decide whether the package lightsim2grid can be used. The package implements a backend for
power flow calculation in C++ and provides a speed-up. If lightsim2grid is "auto" (default), we don't bombard the
user with messages. Otherwise, if lightsim2grid is True bus cannot be used, we inform the user abot it.
Implement some checks to decide whether the package lightsim2grid can be used. These checks are
documentated in :code:`doc\powerflow\ac.rst` The package implements a backend for power flow
calculation in C++ and provides a speed-up. If lightsim2grid
is "auto" (default), we don't bombard the user with messages. Otherwise, if lightsim2grid is
True bus cannot be used, we inform the user abot it.
"""
if not lightsim2grid:
return False # early return :)
Expand Down
Loading

0 comments on commit 2d2aeae

Please sign in to comment.