Asym Line Example
In this notebook we will present examples of asymmetric lines in power-grid-model.
Different input formats are covered. We will do one-time power flow calculation and one-time state estimation.
This notebook serves as an example of how to use the Python API. For detailed API documentation, refer to Python API reference and Native Data Interface.
Asym Line
Asym Line is described as a pi model in power-grid-model, and it belongs to the branch component type which connects two nodes with possibly different voltage levels.
Example Network
We use a simple network with 3 nodes, 1 source, 1 load and 2 asym lines. As shown below:
source_1 --- node_2 --- asym_line_3 --- node_4 --- asym_line_5 --- node_6 --- load_7
# some basic imports
import numpy as np
import pandas as pd
from power_grid_model import (
CalculationMethod,
CalculationType,
ComponentType,
DatasetType,
LoadGenType,
MeasuredTerminalType,
PowerGridModel,
initialize_array,
)
Input Dataset
We create an input dataset by using the helper function initialize_array.
Please refer to Components for detailed explanation of all component types and their input/output attributes.
# node
node = initialize_array(DatasetType.input, ComponentType.node, 3)
node["id"] = np.array([2, 4, 6])
node["u_rated"] = [1e3, 1e3, 1e3]
# load
asym_load = initialize_array(DatasetType.input, ComponentType.asym_load, 1)
asym_load["id"] = [7]
asym_load["node"] = [6]
asym_load["status"] = [1]
asym_load["type"] = [LoadGenType.const_power]
asym_load["p_specified"] = [[1000.0, 2000.0, 3000.0]]
asym_load["q_specified"] = [[1000.0, 2000.0, 3000.0]]
# source
source = initialize_array(DatasetType.input, ComponentType.source, 1)
source["id"] = [1]
source["node"] = [2]
source["status"] = [1]
source["u_ref"] = [1.0]
# asym_line
asym_line = initialize_array(DatasetType.input, ComponentType.asym_line, 2)
asym_line["id"] = [3, 5]
asym_line["from_node"] = [2, 4]
asym_line["to_node"] = [4, 6]
asym_line["from_status"] = [1, 1]
asym_line["to_status"] = [1, 1]
asym_line["r_aa"] = [0.6904, 0.6904]
asym_line["r_ba"] = [0.0495, 0.0495]
asym_line["r_bb"] = [0.6904, 0.6904]
asym_line["r_ca"] = [0.0492, 0.0492]
asym_line["r_cb"] = [0.0495, 0.0495]
asym_line["r_cc"] = [0.6904, 0.6904]
asym_line["r_na"] = [0.0495, np.nan]
asym_line["r_nb"] = [0.0492, np.nan]
asym_line["r_nc"] = [0.0495, np.nan]
asym_line["r_nn"] = [0.6904, np.nan]
asym_line["x_aa"] = [0.8316, 0.8316]
asym_line["x_ba"] = [0.7559, 0.7559]
asym_line["x_bb"] = [0.8316, 0.8316]
asym_line["x_ca"] = [0.7339, 0.7339]
asym_line["x_cb"] = [0.7559, 0.7559]
asym_line["x_cc"] = [0.8316, 0.8316]
asym_line["x_na"] = [0.7559, np.nan]
asym_line["x_nb"] = [0.7339, np.nan]
asym_line["x_nc"] = [0.7559, np.nan]
asym_line["x_nn"] = [0.8316, np.nan]
asym_line["c0"] = [0.32e-9, np.nan]
asym_line["c1"] = [0.54e-9, np.nan]
asym_line["c_aa"] = [np.nan, 0.3200e-09]
asym_line["c_ba"] = [np.nan, 0.5400e-09]
asym_line["c_bb"] = [np.nan, 0.3200e-09]
asym_line["c_ca"] = [np.nan, 0.7600e-09]
asym_line["c_cb"] = [np.nan, 0.5400e-09]
asym_line["c_cc"] = [np.nan, 0.3200e-09]
asym_line["i_n"] = [1000, 1000]
# all
input_data = {
ComponentType.node: node,
ComponentType.asym_line: asym_line,
ComponentType.asym_load: asym_load,
ComponentType.source: source,
}
We can print the input dataset by converting the numpy array to dataframe.
print(pd.DataFrame(input_data[ComponentType.asym_line]))
id from_node to_node from_status to_status r_aa r_ba r_bb \
0 3 2 4 1 1 0.6904 0.0495 0.6904
1 5 4 6 1 1 0.6904 0.0495 0.6904
r_ca r_cb ... x_nn c_aa c_ba c_bb \
0 0.0492 0.0495 ... 0.8316 NaN NaN NaN
1 0.0492 0.0495 ... NaN 3.200000e-10 5.400000e-10 3.200000e-10
c_ca c_cb c_cc c0 c1 \
0 NaN NaN NaN 3.200000e-10 5.400000e-10
1 7.600000e-10 5.400000e-10 3.200000e-10 NaN NaN
i_n
0 1000.0
1 1000.0
[2 rows x 34 columns]
One-time Power Flow Calculation
You can call the method calculate_power_flow to do a one-time calculation based on the current network data in the model.
For detailed explanation of the arguments, batch calculations and asymmetric calculations, we refer to the Power Flow Example and Asymmetric Calculation Example.
# validation (optional)
from power_grid_model.validation import assert_valid_input_data
assert_valid_input_data(input_data=input_data, calculation_type=CalculationType.power_flow)
# construction
model = PowerGridModel(input_data)
# one-time power flow calculation
output_data = model.calculate_power_flow(
symmetric=False, error_tolerance=1e-8, max_iterations=20, calculation_method=CalculationMethod.newton_raphson
)
# result dataset
print("------node voltage result------")
print(pd.DataFrame(output_data[ComponentType.node]["u"]))
print("------node angle result------")
print(pd.DataFrame(output_data[ComponentType.node]["u_angle"]))
------node voltage result------
0 1 2
0 577.350081 577.349890 577.349692
1 577.543188 574.815533 571.914289
2 579.346994 570.159376 567.087326
------node angle result------
0 1 2
0 -2.686835e-07 -2.094396 2.094394
1 4.811479e-05 -2.087729 2.097964
2 2.919948e-03 -2.079969 2.097696
One-time State Estimation
Below we present a simple example of state estimation for a network with two asym lines.
NOTE: In power-grid-model, asym lines belong to branch component type, therefore the measured_terminal_type of power sensors should be assigned to MeasuredTerminalType.branch_from/_to.
For detailed explanation of the arguments, batch calculations and asymmetric calculations, we refer to the State Estimation Example and Asymmetric Calculation Example.
# voltage sensor
asym_voltage_sensor = initialize_array(DatasetType.input, ComponentType.asym_voltage_sensor, 1)
asym_voltage_sensor["id"] = [8]
asym_voltage_sensor["measured_object"] = [6]
asym_voltage_sensor["u_sigma"] = [1.0]
asym_voltage_sensor["u_measured"] = [[1000, 1000, 1000]]
# power sensor
asym_power_sensor = initialize_array(DatasetType.input, ComponentType.asym_power_sensor, 4)
asym_power_sensor["id"] = [9, 10, 11, 12]
asym_power_sensor["measured_object"] = [3, 3, 5, 5]
asym_power_sensor["measured_terminal_type"] = [
MeasuredTerminalType.branch_from,
MeasuredTerminalType.branch_to,
MeasuredTerminalType.branch_from,
MeasuredTerminalType.branch_to,
]
asym_power_sensor["power_sigma"] = [500.0, 500.0, 500.0, 500.0]
asym_power_sensor["p_measured"] = [[1000, 2000, 3000], [1000, 2000, 3000], [1000, 2000, 3000], [1000, 2000, 3000]]
asym_power_sensor["q_measured"] = [[1000, 2000, 3000], [1000, 2000, 3000], [1000, 2000, 3000], [1000, 2000, 3000]]
# use components from former input dataset cell.
input_data2 = {
ComponentType.node: node,
ComponentType.asym_line: asym_line,
ComponentType.asym_load: asym_load,
ComponentType.source: source,
ComponentType.asym_voltage_sensor: asym_voltage_sensor,
ComponentType.asym_power_sensor: asym_power_sensor,
}
# validation (optional)
from power_grid_model.validation import assert_valid_input_data
assert_valid_input_data(input_data=input_data2, calculation_type=CalculationType.state_estimation)
# construction
model2 = PowerGridModel(input_data2)
# one-time state estimation
output_data2 = model2.calculate_state_estimation(
symmetric=False, error_tolerance=1e-8, max_iterations=20, calculation_method=CalculationMethod.iterative_linear
)
# result dataset
print("------node result------")
print(pd.DataFrame(output_data2[ComponentType.node]["u"]))
------node result------
0 1 2
0 1000.000001 999.999991 1000.000007
1 1000.000019 999.999988 999.999997
2 1000.000001 999.999999 999.999999