/pyTranslines

🔌 Controlling a network of electrical transmission lines

Primary LanguagePython

pyTranslines

CodeFactor Grade

This is a python package to control networks of electrical transmission lines. The dynamics on the lines are described by the telegrapher equations, a 2x2 system of PDEs from the class of hyperbolic balance laws. There are two controls inside the network:

  • A so-called outer control to activate or deactivate switches inside the network and thereby disable single lines inside the network (or whole subgrids) at an arbitrary point in time. The outer control is determined by a configuration of the switch states which disable or activate a single line.
  • And a so-called inflow control that determines the power inflow into the network at the source vertices.

Additionally, there are configuration dwell-time constraints to prevent a rapidly switching of the switch states.

The goal is to minimize the sum of quadratic deviation between the given demand and the delivered load to the consumers during a time interval [0, T].

The packages uses a first discretize, then optimize ansatz to transform the infinite dimensional optimization problem on function spaces into a finite dimensional optimization problem. More precisely, the package solves a mixed-integer quadratically constrained quadratic program (MIQCQP) by Gurobi.

Additionally, it contains a specialized heuristic based on the CIAP decomposition to quickly find feasible solutions. This heuristic yields promising results for huge problem instances.

Install

First install pyCIAP. Then, clone this repo and run

python3 setup.py install

inside the repo folder.

Example

Here, u0 and u1 are inflow controls at the source vertices 0 and 1 and Q9, Q10, Q11, Q12, Q13 are given demand functions at the sink (consumer) vertices 9,10,11,12,13. The network contains two switches s1 and s2 to disable lines (or a whole subgrid) inside the network.

The goal is to minimize the sum of quadratic deviation between the demand and the delivered load to the consumers during a time interval [0, T].

from pyTranslines import Translines
import numpy as np

# vertices
V = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

# arcs
A = [(0, 2), (1, 3), (3, 5), (2, 4), (2, 8), (4, 6), (5, 6),
     (6, 7), (8, 7), (2, 9), (8, 10), (3, 11), (7, 12), (7, 13)]

# producer / source vertices
producers = [0, 1]

# consumer / sink vertices
consumers = [9, 10, 11, 12, 13]

# Each config contains the disabled lines if the config is active.
# Example: 2 corresponds to the line A[2] = (3, 5)
configs = [(), (2, 3, 7), (8,), (2, 3, 7, 8)]

# Given consumer demand
demand = np.array([[0.,  0.,  0.,  0., 18.838, 17.444, 16.051, 15.08,
                    14.408, 13.836, 13.488, 13.587, 14.408, 16.026, 17.668, 18.589,
                    19.062, 19.734, 21.401, 24.984, 31.628, 41.358],
                   [0.,  0.,  0.,  0., 18.526, 16.776, 15.526, 14.776,
                    14.351, 14.101, 13.901, 13.626, 13.426, 13.426, 13.676, 14.301,
                    15.976, 19.401, 25.002, 32.827, 41.453, 48.779],
                   [0.,  0.,  0.,  0., 18.526, 16.776, 15.526, 14.776,
                    14.351, 14.101, 13.901, 13.626, 13.426, 13.426, 13.676, 14.301,
                    15.976, 19.401, 25.002, 32.827, 41.453, 48.779],
                   [0.,  0.,  0.,  0., 19.262, 15.536, 12.634, 11.094,
                    10.402,  9.933,  9.665,  9.598,  9.665,  9.754, 10.022, 10.915,
                    13.75, 19.263, 25.089, 28.683, 30.29, 30.736],
                   [0.,  0.,  0.,  0., 19.262, 15.536, 12.634, 11.094,
                    10.402,  9.933,  9.665,  9.598,  9.665,  9.754, 10.022, 10.915,
                    13.75, 19.263, 25.089, 28.683, 30.29, 30.736]])

# end of time horizon [0, T]
T = 10

# Create our discretized control problem
Prob = Translines(V, A, producers, consumers, configs, demand)

# T time horizon, lr length of all network arcs, 
# L, C, R, G physical parameters for all transmission lines 
Prob.set_parameters(T=T, lr=1.0, L=1.0, C=1.0, R=1.0e-3, G=2.0e-3)

# discretization step sizes
Prob.set_step_sizes(dt=0.5, dx=0.5)

# upper bounds for the power inflow at the source vertices
Prob.set_inflow_UB([120, 80])

# Set the configuration dwell times (as number of time steps)
# for all configurations: 3 / dt = 3 / 0.5 = 1.5
Prob.set_min_dwell_times(min_up=3, min_down=3)

# bigM constant used for linearizing the coupling conditions
Prob.set_BigM(150.0)

# Solve via Gurobi, use solver="GurobiCIAP" for the specialized heuristic
Prob.solve(solver="Gurobi")

Prob.plot_results()

Note that the objective function is scaled with factor 1/10 for numerical reasons.