Note

You can download this example as a Jupyter notebook or start it in interactive mode.

Non-linear power flow after LOPF

In this example, the dispatch of generators is optimised using the linear OPF, then a non-linear power flow is run on the resulting dispatch.

Data sources

Grid: based on SciGRID Version 0.2 which is based on OpenStreetMap.

Load size and location: based on Landkreise (NUTS 3) GDP and population.

Load time series: from ENTSO-E hourly data, scaled up uniformly by factor 1.12 (a simplification of the methodology in Schumacher, Hirth (2015)).

Conventional power plant capacities and locations: BNetzA list.

Wind and solar capacities and locations: EEG Stammdaten, based on http://www.energymap.info/download.html, which represents capacities at the end of 2014. Units without PLZ are removed.

Wind and solar time series: REatlas, Andresen et al, “Validation of Danish wind time series from a new global renewable energy atlas for energy system analysis,” Energy 93 (2015) 1074 - 1088.

Where SciGRID nodes have been split into 220kV and 380kV substations, all load and generation is attached to the 220kV substation.

Warnings

The data behind the notebook is no longer supported. See https://github.com/PyPSA/pypsa-eur for a newer model that covers the whole of Europe.

This dataset is ONLY intended to demonstrate the capabilities of PyPSA and is NOT (yet) accurate enough to be used for research purposes.

Known problems include:

  1. Rough approximations have been made for missing grid data, e.g. 220kV-380kV transformers and connections between close sub-stations missing from OSM.

  2. There appears to be some unexpected congestion in parts of the network, which may mean for example that the load attachment method (by Voronoi cell overlap with Landkreise) isn’t working, particularly in regions with a high density of substations.

  3. Attaching power plants to the nearest high voltage substation may not reflect reality.

  4. There is no proper n-1 security in the calculations - this can either be simulated with a blanket e.g. 70% reduction in thermal limits (as done here) or a proper security constrained OPF (see e.g. http://www.pypsa.org/examples/scigrid-sclopf.ipynb).

  5. The borders and neighbouring countries are not represented.

  6. Hydroelectric power stations are not modelled accurately.

  7. The marginal costs are illustrative, not accurate.

  8. Only the first day of 2011 is in the github dataset, which is not representative. The full year of 2011 can be downloaded at http://www.pypsa.org/examples/scigrid-with-load-gen-trafos-2011.zip.

  9. The ENTSO-E total load for Germany may not be scaled correctly; it is scaled up uniformly by factor 1.12 (a simplification of the methodology in Schumacher, Hirth (2015), which suggests monthly factors).

  10. Biomass from the EEG Stammdaten are not read in at the moment.

  11. Power plant start up costs, ramping limits/costs, minimum loading rates are not considered.

[1]:
import pypsa
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import cartopy.crs as ccrs

%matplotlib inline
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In [1], line 1
----> 1 import pypsa
      2 import numpy as np
      3 import pandas as pd

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/pypsa/__init__.py:10
      1 # -*- coding: utf-8 -*-
      4 """
      5 Python for Power Systems Analysis (PyPSA)
      6
      7 Grid calculation library.
      8 """
---> 10 from pypsa import (
     11     components,
     12     contingency,
     13     descriptors,
     14     examples,
     15     geo,
     16     io,
     17     linopf,
     18     linopt,
     19     networkclustering,
     20     opf,
     21     opt,
     22     optimization,
     23     pf,
     24     plot,
     25 )
     26 from pypsa.components import Network, SubNetwork
     28 __version__ = "0.21.2"

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/pypsa/components.py:50
     37 from pypsa.io import (
     38     export_to_csv_folder,
     39     export_to_hdf5,
   (...)
     47     import_series_from_dataframe,
     48 )
     49 from pypsa.opf import network_lopf, network_opf
---> 50 from pypsa.optimization.optimize import OptimizationAccessor
     51 from pypsa.pf import (
     52     calculate_B_H,
     53     calculate_dependent_values,
   (...)
     62     sub_network_pf,
     63 )
     64 from pypsa.plot import iplot, plot

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/pypsa/optimization/__init__.py:7
      1 #!/usr/bin/env python3
      2 # -*- coding: utf-8 -*-
      3 """
      4 Build optimisation problems from PyPSA networks with Linopy.
      5 """
----> 7 from pypsa.optimization import abstract, constraints, optimize, variables
      8 from pypsa.optimization.optimize import create_model

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/pypsa/optimization/constraints.py:9
      6 import logging
      8 import pandas as pd
----> 9 from linopy.expressions import LinearExpression, merge
     10 from numpy import arange, cumsum, inf, nan, roll
     11 from scipy import sparse

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/linopy/__init__.py:9
      1 #!/usr/bin/env python3
      2 # -*- coding: utf-8 -*-
      3 """
      4 Created on Wed Mar 10 11:03:06 2021.
      5
      6 @author: fabulous
      7 """
----> 9 from linopy import model, remote
     10 from linopy.expressions import merge
     11 from linopy.io import read_netcdf

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/linopy/model.py:22
     20 from linopy import solvers
     21 from linopy.common import best_int, replace_by_map
---> 22 from linopy.constraints import (
     23     AnonymousConstraint,
     24     AnonymousScalarConstraint,
     25     Constraints,
     26 )
     27 from linopy.eval import Expr
     28 from linopy.expressions import LinearExpression, ScalarLinearExpression

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/linopy/constraints.py:21
     18 from scipy.sparse import coo_matrix
     19 from xarray import DataArray, Dataset
---> 21 from linopy import expressions, variables
     22 from linopy.common import (
     23     _merge_inplace,
     24     has_assigned_model,
   (...)
     27     replace_by_map,
     28 )
     31 class Constraint(DataArray):

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/linopy/expressions.py:23
     20 from xarray.core.dataarray import DataArrayCoordinates
     21 from xarray.core.groupby import _maybe_reorder, peek_at
---> 23 from linopy import constraints, variables
     24 from linopy.common import as_dataarray
     27 def exprwrap(method, *default_args, **new_default_kwargs):

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/site-packages/linopy/variables.py:398
    393     roll = varwrap(DataArray.roll)
    395     rolling = varwrap(DataArray.rolling)
--> 398 @dataclass(repr=False)
    399 class Variables:
    400     """
    401     A variables container used for storing multiple variable arrays.
    402     """
    404     labels: Dataset = Dataset()

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/dataclasses.py:1211, in dataclass.<locals>.wrap(cls)
   1210 def wrap(cls):
-> 1211     return _process_class(cls, init, repr, eq, order, unsafe_hash,
   1212                           frozen, match_args, kw_only, slots,
   1213                           weakref_slot)

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/dataclasses.py:959, in _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, match_args, kw_only, slots, weakref_slot)
    956         kw_only = True
    957     else:
    958         # Otherwise it's a field of some type.
--> 959         cls_fields.append(_get_field(cls, name, type, kw_only))
    961 for f in cls_fields:
    962     fields[f.name] = f

File ~/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.21.2/lib/python3.11/dataclasses.py:816, in _get_field(cls, a_name, a_type, default_kw_only)
    812 # For real fields, disallow mutable defaults.  Use unhashable as a proxy
    813 # indicator for mutability.  Read the __hash__ attribute from the class,
    814 # not the instance.
    815 if f._field_type is _FIELD and f.default.__class__.__hash__ is None:
--> 816     raise ValueError(f'mutable default {type(f.default)} for field '
    817                      f'{f.name} is not allowed: use default_factory')
    819 return f

ValueError: mutable default <class 'xarray.core.dataset.Dataset'> for field labels is not allowed: use default_factory
[2]:
network = pypsa.examples.scigrid_de(from_master=True)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [2], line 1
----> 1 network = pypsa.examples.scigrid_de(from_master=True)

NameError: name 'pypsa' is not defined

Plot the distribution of the load and of generating tech

[3]:
fig, ax = plt.subplots(
    1, 1, subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(8, 8)
)

load_distribution = (
    network.loads_t.p_set.loc[network.snapshots[0]].groupby(network.loads.bus).sum()
)
network.plot(bus_sizes=1e-5 * load_distribution, ax=ax, title="Load distribution");
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [3], line 1
----> 1 fig, ax = plt.subplots(
      2     1, 1, subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(8, 8)
      3 )
      5 load_distribution = (
      6     network.loads_t.p_set.loc[network.snapshots[0]].groupby(network.loads.bus).sum()
      7 )
      8 network.plot(bus_sizes=1e-5 * load_distribution, ax=ax, title="Load distribution");

NameError: name 'plt' is not defined
[4]:
network.generators.groupby("carrier")["p_nom"].sum()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [4], line 1
----> 1 network.generators.groupby("carrier")["p_nom"].sum()

NameError: name 'network' is not defined
[5]:
network.storage_units.groupby("carrier")["p_nom"].sum()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [5], line 1
----> 1 network.storage_units.groupby("carrier")["p_nom"].sum()

NameError: name 'network' is not defined
[6]:
techs = ["Gas", "Brown Coal", "Hard Coal", "Wind Offshore", "Wind Onshore", "Solar"]

n_graphs = len(techs)
n_cols = 3
if n_graphs % n_cols == 0:
    n_rows = n_graphs // n_cols
else:
    n_rows = n_graphs // n_cols + 1


fig, axes = plt.subplots(
    nrows=n_rows, ncols=n_cols, subplot_kw={"projection": ccrs.EqualEarth()}
)
size = 6
fig.set_size_inches(size * n_cols, size * n_rows)

for i, tech in enumerate(techs):
    i_row = i // n_cols
    i_col = i % n_cols

    ax = axes[i_row, i_col]
    gens = network.generators[network.generators.carrier == tech]
    gen_distribution = (
        gens.groupby("bus").sum()["p_nom"].reindex(network.buses.index, fill_value=0.0)
    )
    network.plot(ax=ax, bus_sizes=2e-5 * gen_distribution)
    ax.set_title(tech)
fig.tight_layout()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [6], line 11
      7 else:
      8     n_rows = n_graphs // n_cols + 1
---> 11 fig, axes = plt.subplots(
     12     nrows=n_rows, ncols=n_cols, subplot_kw={"projection": ccrs.EqualEarth()}
     13 )
     14 size = 6
     15 fig.set_size_inches(size * n_cols, size * n_rows)

NameError: name 'plt' is not defined

Run Linear Optimal Power Flow on the first day of 2011.

To approximate n-1 security and allow room for reactive power flows, don’t allow any line to be loaded above 70% of their thermal rating

[7]:
contingency_factor = 0.7
network.lines.s_max_pu = contingency_factor
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [7], line 2
      1 contingency_factor = 0.7
----> 2 network.lines.s_max_pu = contingency_factor

NameError: name 'network' is not defined

There are some infeasibilities without small extensions

[8]:
network.lines.loc[["316", "527", "602"], "s_nom"] = 1715
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [8], line 1
----> 1 network.lines.loc[["316", "527", "602"], "s_nom"] = 1715

NameError: name 'network' is not defined

We performing a linear OPF for one day, 4 snapshots at a time.

[9]:
group_size = 4
network.storage_units.state_of_charge_initial = 0.0

for i in range(int(24 / group_size)):
    # set the initial state of charge based on previous round
    if i:
        network.storage_units.state_of_charge_initial = (
            network.storage_units_t.state_of_charge.loc[
                network.snapshots[group_size * i - 1]
            ]
        )
    network.lopf(
        network.snapshots[group_size * i : group_size * i + group_size],
        solver_name="cbc",
        pyomo=False,
    )
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [9], line 2
      1 group_size = 4
----> 2 network.storage_units.state_of_charge_initial = 0.0
      4 for i in range(int(24 / group_size)):
      5     # set the initial state of charge based on previous round
      6     if i:

NameError: name 'network' is not defined
[10]:
p_by_carrier = network.generators_t.p.groupby(network.generators.carrier, axis=1).sum()
p_by_carrier.drop(
    (p_by_carrier.max()[p_by_carrier.max() < 1700.0]).index, axis=1, inplace=True
)
p_by_carrier.columns
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [10], line 1
----> 1 p_by_carrier = network.generators_t.p.groupby(network.generators.carrier, axis=1).sum()
      2 p_by_carrier.drop(
      3     (p_by_carrier.max()[p_by_carrier.max() < 1700.0]).index, axis=1, inplace=True
      4 )
      5 p_by_carrier.columns

NameError: name 'network' is not defined
[11]:
colors = {
    "Brown Coal": "brown",
    "Hard Coal": "k",
    "Nuclear": "r",
    "Run of River": "green",
    "Wind Onshore": "blue",
    "Solar": "yellow",
    "Wind Offshore": "cyan",
    "Waste": "orange",
    "Gas": "orange",
}
# reorder
cols = [
    "Nuclear",
    "Run of River",
    "Brown Coal",
    "Hard Coal",
    "Gas",
    "Wind Offshore",
    "Wind Onshore",
    "Solar",
]
p_by_carrier = p_by_carrier[cols]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [11], line 23
     12 # reorder
     13 cols = [
     14     "Nuclear",
     15     "Run of River",
   (...)
     21     "Solar",
     22 ]
---> 23 p_by_carrier = p_by_carrier[cols]

NameError: name 'p_by_carrier' is not defined
[12]:
c = [colors[col] for col in p_by_carrier.columns]

fig, ax = plt.subplots(figsize=(12, 6))
(p_by_carrier / 1e3).plot(kind="area", ax=ax, linewidth=4, color=c, alpha=0.7)
ax.legend(ncol=4, loc="upper left")
ax.set_ylabel("GW")
ax.set_xlabel("")
fig.tight_layout()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [12], line 1
----> 1 c = [colors[col] for col in p_by_carrier.columns]
      3 fig, ax = plt.subplots(figsize=(12, 6))
      4 (p_by_carrier / 1e3).plot(kind="area", ax=ax, linewidth=4, color=c, alpha=0.7)

NameError: name 'p_by_carrier' is not defined
[13]:
fig, ax = plt.subplots(figsize=(12, 6))

p_storage = network.storage_units_t.p.sum(axis=1)
state_of_charge = network.storage_units_t.state_of_charge.sum(axis=1)
p_storage.plot(label="Pumped hydro dispatch", ax=ax, linewidth=3)
state_of_charge.plot(label="State of charge", ax=ax, linewidth=3)

ax.legend()
ax.grid()
ax.set_ylabel("MWh")
ax.set_xlabel("")
fig.tight_layout()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [13], line 1
----> 1 fig, ax = plt.subplots(figsize=(12, 6))
      3 p_storage = network.storage_units_t.p.sum(axis=1)
      4 state_of_charge = network.storage_units_t.state_of_charge.sum(axis=1)

NameError: name 'plt' is not defined
[14]:
now = network.snapshots[4]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [14], line 1
----> 1 now = network.snapshots[4]

NameError: name 'network' is not defined

With the linear load flow, there is the following per unit loading:

[15]:
loading = network.lines_t.p0.loc[now] / network.lines.s_nom
loading.describe()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [15], line 1
----> 1 loading = network.lines_t.p0.loc[now] / network.lines.s_nom
      2 loading.describe()

NameError: name 'network' is not defined
[16]:
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(9, 9))
network.plot(
    ax=ax,
    line_colors=abs(loading),
    line_cmap=plt.cm.jet,
    title="Line loading",
    bus_sizes=1e-3,
    bus_alpha=0.7,
)
fig.tight_layout();
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [16], line 1
----> 1 fig, ax = plt.subplots(subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(9, 9))
      2 network.plot(
      3     ax=ax,
      4     line_colors=abs(loading),
   (...)
      8     bus_alpha=0.7,
      9 )
     10 fig.tight_layout();

NameError: name 'plt' is not defined

Let’s have a look at the marginal prices

[17]:
network.buses_t.marginal_price.loc[now].describe()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [17], line 1
----> 1 network.buses_t.marginal_price.loc[now].describe()

NameError: name 'network' is not defined
[18]:
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}, figsize=(8, 8))

plt.hexbin(
    network.buses.x,
    network.buses.y,
    gridsize=20,
    C=network.buses_t.marginal_price.loc[now],
    cmap=plt.cm.jet,
    zorder=3,
)
network.plot(ax=ax, line_widths=pd.Series(0.5, network.lines.index), bus_sizes=0)

cb = plt.colorbar(location="bottom")
cb.set_label("Locational Marginal Price (EUR/MWh)")
fig.tight_layout()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [18], line 1
----> 1 fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}, figsize=(8, 8))
      3 plt.hexbin(
      4     network.buses.x,
      5     network.buses.y,
   (...)
      9     zorder=3,
     10 )
     11 network.plot(ax=ax, line_widths=pd.Series(0.5, network.lines.index), bus_sizes=0)

NameError: name 'plt' is not defined

Curtailment variable

By considering how much power is available and how much is generated, you can see what share is curtailed:

[19]:
carrier = "Wind Onshore"

capacity = network.generators.groupby("carrier").sum().at[carrier, "p_nom"]
p_available = network.generators_t.p_max_pu.multiply(network.generators["p_nom"])
p_available_by_carrier = p_available.groupby(network.generators.carrier, axis=1).sum()
p_curtailed_by_carrier = p_available_by_carrier - p_by_carrier
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [19], line 3
      1 carrier = "Wind Onshore"
----> 3 capacity = network.generators.groupby("carrier").sum().at[carrier, "p_nom"]
      4 p_available = network.generators_t.p_max_pu.multiply(network.generators["p_nom"])
      5 p_available_by_carrier = p_available.groupby(network.generators.carrier, axis=1).sum()

NameError: name 'network' is not defined
[20]:
p_df = pd.DataFrame(
    {
        carrier + " available": p_available_by_carrier[carrier],
        carrier + " dispatched": p_by_carrier[carrier],
        carrier + " curtailed": p_curtailed_by_carrier[carrier],
    }
)

p_df[carrier + " capacity"] = capacity
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [20], line 1
----> 1 p_df = pd.DataFrame(
      2     {
      3         carrier + " available": p_available_by_carrier[carrier],
      4         carrier + " dispatched": p_by_carrier[carrier],
      5         carrier + " curtailed": p_curtailed_by_carrier[carrier],
      6     }
      7 )
      9 p_df[carrier + " capacity"] = capacity

NameError: name 'pd' is not defined
[21]:
p_df["Wind Onshore curtailed"][p_df["Wind Onshore curtailed"] < 0.0] = 0.0
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [21], line 1
----> 1 p_df["Wind Onshore curtailed"][p_df["Wind Onshore curtailed"] < 0.0] = 0.0

NameError: name 'p_df' is not defined
[22]:
fig, ax = plt.subplots(figsize=(10, 4))
p_df[[carrier + " dispatched", carrier + " curtailed"]].plot(
    kind="area", ax=ax, linewidth=3
)
p_df[[carrier + " available", carrier + " capacity"]].plot(ax=ax, linewidth=3)

ax.set_xlabel("")
ax.set_ylabel("Power [MW]")
ax.set_ylim([0, 40000])
ax.legend()
fig.tight_layout()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [22], line 1
----> 1 fig, ax = plt.subplots(figsize=(10, 4))
      2 p_df[[carrier + " dispatched", carrier + " curtailed"]].plot(
      3     kind="area", ax=ax, linewidth=3
      4 )
      5 p_df[[carrier + " available", carrier + " capacity"]].plot(ax=ax, linewidth=3)

NameError: name 'plt' is not defined

Non-Linear Power Flow

Now perform a full Newton-Raphson power flow on the first hour. For the PF, set the P to the optimised P.

[23]:
network.generators_t.p_set = network.generators_t.p
network.storage_units_t.p_set = network.storage_units_t.p
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [23], line 1
----> 1 network.generators_t.p_set = network.generators_t.p
      2 network.storage_units_t.p_set = network.storage_units_t.p

NameError: name 'network' is not defined

Set all buses to PV, since we don’t know what Q set points are

[24]:
network.generators.control = "PV"

# Need some PQ buses so that Jacobian doesn't break
f = network.generators[network.generators.bus == "492"]
network.generators.loc[f.index, "control"] = "PQ"
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [24], line 1
----> 1 network.generators.control = "PV"
      3 # Need some PQ buses so that Jacobian doesn't break
      4 f = network.generators[network.generators.bus == "492"]

NameError: name 'network' is not defined

Now, perform the non-linear PF.

[25]:
info = network.pf();
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [25], line 1
----> 1 info = network.pf();

NameError: name 'network' is not defined

Any failed to converge?

[26]:
(~info.converged).any().any()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [26], line 1
----> 1 (~info.converged).any().any()

NameError: name 'info' is not defined

With the non-linear load flow, there is the following per unit loading of the full thermal rating.

[27]:
(network.lines_t.p0.loc[now] / network.lines.s_nom).describe()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [27], line 1
----> 1 (network.lines_t.p0.loc[now] / network.lines.s_nom).describe()

NameError: name 'network' is not defined

Let’s inspect the voltage angle differences across the lines have (in degrees)

[28]:
df = network.lines.copy()

for b in ["bus0", "bus1"]:
    df = pd.merge(
        df, network.buses_t.v_ang.loc[[now]].T, how="left", left_on=b, right_index=True
    )

s = df[str(now) + "_x"] - df[str(now) + "_y"]

(s * 180 / np.pi).describe()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [28], line 1
----> 1 df = network.lines.copy()
      3 for b in ["bus0", "bus1"]:
      4     df = pd.merge(
      5         df, network.buses_t.v_ang.loc[[now]].T, how="left", left_on=b, right_index=True
      6     )

NameError: name 'network' is not defined

Plot the reactive power

[29]:
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(9, 9))

q = network.buses_t.q.loc[now]
bus_colors = pd.Series("r", network.buses.index)
bus_colors[q < 0.0] = "b"

network.plot(
    bus_sizes=1e-4 * abs(q),
    ax=ax,
    bus_colors=bus_colors,
    title="Reactive power feed-in (red=+ve, blue=-ve)",
);
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In [29], line 1
----> 1 fig, ax = plt.subplots(subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(9, 9))
      3 q = network.buses_t.q.loc[now]
      4 bus_colors = pd.Series("r", network.buses.index)

NameError: name 'plt' is not defined