Simple Time Series Example

This tutorial shows how a simple time series simulation is performed with the timeseries and control module in pandapower. A time series calculation requires the minimum following inputs:

  • pandapower net
  • the time series (in a pandas Dataframe for example)

First we need some imports. Specific for this example are:

  • ConstControl -> "constant" controllers, which change the P and Q values of sgens and loads
  • DFData -> The Dataframe Datasource. This Dataframe holds the time series to be calculated
  • OutputWriter -> The output writer, which is required to write the outputs to the hard disk
  • run_timeseries -> the "main" time series function, which basically calls the controller functions (to update the P, Q of the ConstControllers) and runpp.
In [0]:
import os
import numpy as np
import pandas as pd
import tempfile

import pandapower as pp
from pandapower.timeseries import DFData
from pandapower.timeseries import OutputWriter
from pandapower.timeseries.run_time_series import run_timeseries
from pandapower.control import ConstControl

First we look at the time series example function. It follows these steps:

  1. create a simple test net
  2. create the datasource (which contains the time series P values)
  3. create the controllers to update the P values of the load and the sgen
  4. define the output writer and desired variables to be saved
  5. call the main time series function to calculate the desired results
In [0]:
def timeseries_example(output_dir):
    # 1. create test net
    net = simple_test_net()

    # 2. create (random) data source
    n_timesteps = 24
    profiles, ds = create_data_source(n_timesteps)
    # 3. create controllers (to control P values of the load and the sgen)
    create_controllers(net, ds)

    # time steps to be calculated. Could also be a list with non-consecutive time steps
    time_steps = range(0, n_timesteps)

    # 4. the output writer with the desired results to be stored to files.
    ow = create_output_writer(net, time_steps, output_dir=output_dir)

    # 5. the main time series function
    run_timeseries(net, time_steps, output_writer=ow)

We start by creating a simple example pandapower net consinsting of five buses, a transfomer, three lines, a load and a sgen.

In [0]:
def simple_test_net():
    """
    simple net that looks like:

    ext_grid b0---b1 trafo(110/20) b2----b3 load
                                    |
                                    |
                                    b4 sgen
    """
    net = pp.create_empty_network()
    pp.set_user_pf_options(net, init_vm_pu = "flat", init_va_degree = "dc", calculate_voltage_angles=True)

    b0 = pp.create_bus(net, 110)
    b1 = pp.create_bus(net, 110)
    b2 = pp.create_bus(net, 20)
    b3 = pp.create_bus(net, 20)
    b4 = pp.create_bus(net, 20)

    pp.create_ext_grid(net, b0)
    pp.create_line(net, b0, b1, 10, "149-AL1/24-ST1A 110.0")
    pp.create_transformer(net, b1, b2, "25 MVA 110/20 kV", name='tr1')
    pp.create_line(net, b2, b3, 10, "184-AL1/30-ST1A 20.0")
    pp.create_line(net, b2, b4, 10, "184-AL1/30-ST1A 20.0")

    pp.create_load(net, b2, p_mw=20., q_mvar=10., name='load1')
    pp.create_sgen(net, b4, p_mw=20., q_mvar=0.15, name='sgen1')

    return net

The data source is a simple pandas DataFrame. It contains random values for the load and the sgen P values ("profiles"). Of course your time series values should be loaded from a file later on. Note that the profiles are identified by their column name ("load1_p", "sgen1_p"). You can choose here whatever you prefer. The DFData(profiles) converts the Dataframe to the required format for the controllers. Note that the controller

In [0]:
def create_data_source(n_timesteps=24):
    profiles = pd.DataFrame()
    profiles['load1_p'] = np.random.random(n_timesteps) * 20.
    profiles['sgen1_p'] = np.random.random(n_timesteps) * 20.

    ds = DFData(profiles)

    return profiles, ds

create the controllers by telling the function which element_index belongs to which profile. In this case we map:

  • first load in dataframe (element_index=[0]) to the profile_name "load1_p"
  • first sgen in dataframe (element_index=[0]) to the profile_name "sgen1_p"
In [0]:
def create_controllers(net, ds):
    ConstControl(net, element='load', variable='p_mw', element_index=[0],
                 data_source=ds, profile_name=["load1_p"])
    ConstControl(net, element='sgen', variable='p_mw', element_index=[0],
                 data_source=ds, profile_name=["sgen1_p"])

create the output writer. Instead of saving the whole net (which takes a lot of time), we extract only pre defined outputs. In this case we:

  • save the results to "../timeseries/tests/outputs"
  • write the results to ".xls" Excel files. (Possible are: .json, .p, .csv)
  • log the variables "p_mw" from "res_load", "vm_pu" from "res_bus" and two res_line values.
In [0]:
def create_output_writer(net, time_steps, output_dir):
    ow = OutputWriter(net, time_steps, output_path=output_dir, output_file_type=".xls")
    # these variables are saved to the harddisk after / during the time series loop
    ow.log_variable('res_load', 'p_mw')
    ow.log_variable('res_bus', 'vm_pu')
    ow.log_variable('res_line', 'loading_percent')
    ow.log_variable('res_line', 'i_ka')
    return ow

Now lets execude the code.

In [0]:
output_dir = os.path.join(tempfile.gettempdir(), "time_series_example")
print("Results can be found in your local temp folder: {}".format(output_dir))
if not os.path.exists(output_dir):
    os.mkdir(output_dir)
timeseries_example(output_dir)
Results can be found in your local temp folder: /tmp/time_series_example
Progress: |██████████████████████████████████████████████████| 100.0% Complete

If everything works you should have the desired results the output_folder, which is the temporary folder of your operating system (see print statement above).

Plot the result

Let's read the result from the disk and plot it

In [0]:
import matplotlib.pyplot as plt
%matplotlib inline  

# voltage results
vm_pu_file = os.path.join(output_dir, "res_bus", "vm_pu.xls")
vm_pu = pd.read_excel(vm_pu_file)
vm_pu.plot(label="vm_pu")
plt.xlabel("time step")
plt.ylabel("voltage mag. [p.u.]")
plt.title("Voltage Magnitude")
plt.grid()
plt.show()

# line loading results
ll_file = os.path.join(output_dir, "res_line", "loading_percent.xls")
line_loading = pd.read_excel(ll_file)
line_loading.plot(label="line_loading")
plt.xlabel("time step")
plt.ylabel("line loading [%]")
plt.title("Line Loading")
plt.grid()
plt.show()

# load results
load_file = os.path.join(output_dir, "res_load", "p_mw.xls")
load = pd.read_excel(load_file)
load.plot(label="load")
plt.xlabel("time step")
plt.ylabel("P [MW]")
plt.grid()
plt.show()
In [0]:
 
In [0]: