The Protection settings optimizer (PSO) is a Python package for calculating optimal protection settings for power systems protection devices such as relays and reclosers. The PSO algorithm uses supplied network data and fault analysis to generate settings with minimal operating times while maintaining coordination between protection devices. The network data is used to identify protection device coordination pairs using graph theory-based path tracing. The fault analysis provides the fault currents observed at each protection device. The fault currents and the coordination pairs are used to formulate the relay settings as a mixed integer nonlinear problem (MINLP). The MINLP is solved using a genetic algorithm-based solver. The figure below provides an overview of the protection settings optimizer process.
保護設定優化器 (Protection settings optimizer, PSO) 是一個用於計算電力系統保護裝置(如繼電器和重合器)最佳保護設定的 Python 套件。PSO 演算法利用提供的網路數據和故障分析來生成具有最小操作時間的設定,同時保持保護裝置之間的協調。網路數據用於使用基於圖論的路徑追蹤來識別保護裝置協調對。故障分析提供在每個保護裝置上觀察到的故障電流。故障電流和協調對用於將繼電器設定公式化為混合整數非線性問題 (MINLP)。該 MINLP 使用基於遺傳演算法的求解器進行求解。下圖提供了保護設定優化器過程的概述。
python -m pip install git+https://github.com/sandialabs/Protection-settings-optimizer.git
The system information required to run the settings optimizer can be obtained in the following methods
執行設定優化器所需的系統資訊可以透過以下方法獲得
1) Json Format
1) Json 格式
The system information can be imported using a JSON file. The JSON file must contain at least the following information with the labels shown below:
系統資訊可以使用 JSON 檔案匯入。該 JSON 檔案必須至少包含以下資訊,並顯示相應的標籤:
- Relays/Reclosers
- Name: Relay Name
- Bus1: From Bus
- Bus2: To Bus
- MonitoredObj: Name of branch connecting Bus1 and Bus2
- Enabled: True or False
- Lines
- Name: Name of Line
- Bus1: From Bus
- Bus2: To bus
- Enabled: True or False
- numPhases: number of phases
- Length: Line length
- Rpu: perunit line resistacne
- Xpu: per-unit line reactance
- XFMRS
- Name: Name of Transformer
- Bus1: From Bus
- Bus2: To bus
- Enabled: True or false
- nunPhases: number of phases
- Rpu: perunit resistacne
- Xpu: per-unit reactance
- Buses
- Name: Bus name
- numPhases: number of phases
- kV: Bus nominal Line-ground voltage in kV (optional)
- x: x coordinate for plotting (optional)
- y: y coordinate for plotting (optional)
- Pvs
- Name: Name of PV generation
- Bus: Location of PV generation
- Enabled: True or False
- numPhases: Number of phases
- BESS
- Name: Name of Battery Energy Storage System (BESS)
- Bus: Location of Battery
- Enabled: True or False
- numPhases: Number of phases
- Gens
- Name: Name of the generator (traditional or distributed)
- Bus: Loacaation of generator
- Enabled: True or False
- numPhases: Number of phases
2) Import from OpenDSS
2) 從 OpenDSS 匯入
The system information can be obtained from OpenDSS directly using the COM interface. The following code can be used to start OpenDSS and request the required system information.
系統資訊可以直接從 OpenDSS 獲取,使用 COM 介面。以下程式碼可用於啟動 OpenDSS 並請求所需的系統資訊。
import os
import RSO_pack
import win32com.client
# Start OpenDSS
dssObj = win32com.client.Dispatch("OpenDSSEngine.DSS")
dssText = dssObj.Text
dssCircuit = dssObj.ActiveCircuit
dssSolution = dssCircuit.Solution
dssElem = dssCircuit.ActiveCktElement
dssBus = dssCircuit.ActiveBus
# Start Run IEEE 34 bus system
dssText.Command = 'clear'
dssText.Command = 'compile 'Path to OpenDss file'
dssText.command = 'set maxcontroliter = 500'
dssText.Command = 'solve'
# collect system info from OpenDSS
SysInfo = RSO_pack.getSysInfo(dssCircuit)
3) RONM json File
3) RONM JSON 檔案
The system information can also be parsed from the RONM Output using the code below.
系統資訊也可以使用以下代碼從 RONM 輸出中解析。
# Load RONM output
jsonFile = "loaction of RONM output json file"
f = open(jsonFile)
jsonDict = json.load(f)
f.close()
# Get SysInfo from Json
proSettings = jsonDict['Protection settings']
powerFlow = jsonDict['Powerflow output']
SysInfo = RSO_pack.getRONMSysInfo(proSettings,powerFlow)
The RONM output must contain the necessary system information in 'Protection settings/network_model'.
The protection settings optimizer requires the steady state/load flow data to calculate settings.
The steady-state information can be obtained from the following sources:
保護設定優化器需要穩態/負載流數據來計算設定。穩態資訊可以從以下來源獲得:
1) CSV File
1) CSV 檔案
A ".CSV" file containing the following information for each protection device:
一個包含每個保護裝置以下資訊的 ".CSV" 檔案:
- Device index
- Phasors
- [Va,Vb,Vc,Ia,Ib,Ic]
- Voltages in volts
- Currents in Amps
- angles in radians
- Digital: Protection device breaker status
- 1: closed
- 0: Open
- Per phase real power
RelayName | phasors | digital | RealPower | |
---|---|---|---|---|
0 | SEL-751-1 | [(2330.68, 2.46),(2370.47, 0.39),(2355.01,-1.70),(426.32,2.25),(255.44,0.18),(310.66,-1.89)] | [1] | [971748.37, 591362.89, 717722.91] |
2) Import from OpenDSS
2) 從 OpenDSS 匯入
The steady-state/load flow information can be obtained from OpenDSS directly using the COM interface using the code below.
穩態/負載流資訊可以直接從 OpenDSS 獲取,使用下面的 COM 介面代碼。
%% collect steady state Data
Buses = SysInfo['Buses']
devLines = [x['MonitoredObj'].split('line.')[1] for x in SysInfo['Relays']]+[x['MonitoredObj'].split('line.')[1] for x in SysInfo['Recs']]
devNames = [x['Name'] for x in SysInfo['Relays']]+[x['Name'] for x in SysInfo['Recs']]
dev_BusV = [Buses[RSO_pack.index_dict(Buses,'Name',x['Bus1'])]['kV']*1e3 for x in SysInfo['Relays'] ]+[Buses[RSO_pack.index_dict(Buses,'Name',x['Bus1'])]['kV']*1e3 for x in SysInfo['Recs'] ]
Device_Data_CSV = RSO_pack.getDeviceData(dssCircuit,devNames,devLines,dev_BusV)
3) Import from RONM
3) 從 RONM 匯入
The steady-state/load flow information for each timestep included in the RONM output can be obtained from the "Powerflow output/protection" section.
The section must contain an entry for each protection device for each time step.
Each device entry must contain the following:
1. voltage (kV) : Voltage magnitude
2. phi (deg) : Voltage angle
3. real power flow (kW)
4. reactive power flow (kVar)
RONM 輸出中每個時間步的穩態/負載流資訊可以從「功率流輸出/保護」部分獲得。該部分必須包含每個保護裝置在每個時間步的條目。每個裝置條目必須包含以下內容:1. 電壓 (kV):電壓幅值 2. phi (度):電壓角度 3. 實功率流 (kW) 4. 無功率流 (kVar)
The following code can be used to obtain the steady-state values.
proSettings = jsonDict['Protection settings']
powerFlow = jsonDict['Powerflow output']
SysInfo = RSO_pack.getRONMSysInfo(proSettings,powerFlow,ignore_fuse=True)
# Get Timeline Data form Json
devTimeLine = jsonDict['Device action timeline']
(sW_Status,sW_Names) = RSO_pack.get_Sw_Status(jsonDict['Powerflow output'],devTimeLine)
# %% Calculate devie Data
Buses = SysInfo['Buses']
Relay_list = [x['MonitoredObj'].split('line.')[1] for x in SysInfo['Relays']]
Reclo_list = [x['MonitoredObj'].split('line.')[1] for x in SysInfo['Recs']]
Fuses_list = [x['MonitoredObj'].split('line.')[1] for x in SysInfo['Fuses']]
devTypes = ['relay']*len(Relay_list)+['recloser']*len(Reclo_list)+['fuse']*len(Fuses_list)
devLines = Relay_list+Reclo_list+Fuses_list
devNames = [x['Name'] for x in SysInfo['Relays']]+[x['Name'] for x in SysInfo['Recs']]+[x['Name'] for x in SysInfo['Fuses']]
dev_BusV = [Buses[RSO_pack.index_dict(Buses,'Name',x['Bus1'])]['kV']*1e3 for x in SysInfo['Relays']]+[Buses[RSO_pack.index_dict(Buses,'Name',x['Bus1'])]['kV']*1e3 for x in SysInfo['Recs']]+[Buses[RSO_pack.index_dict(Buses,'Name',x['Bus1'])]['kV']*1e3 for x in SysInfo['Fuses']]
# create settings list
settings = []*len(devTimeLine)
# %% itterate per step
for Ts in range(len(devTimeLine)):
print('------======'+str(Ts)+'======------\n')
# get switch states
switchLines = sW_Names
switchStates = sW_Status[Ts]
# Collect Load Flow Deta
Device_Data_CSV = RSO_pack.getRONMDeviceData(Ts,powerFlow,devTypes,devNames,devLines,dev_BusV,SysInfo,sW_Status,sW_Names)
The protection settings optimizer requires fault analysis data to calculate the protection settings. Similarly to the system information and steady-state data, one of three methods can be used to import fault data.
保護設定優化器需要故障分析數據來計算保護設定。與系統資訊和穩態數據類似,可以使用三種方法之一來導入故障數據。
1) Import from CSV
1) 從 CSV 導入
A ".CSV" file containing the following information for each fault at each protection device can be used to import the fault data.
可以使用包含每個保護裝置每個故障的以下資訊的 ".CSV" 檔案來匯入故障數據。
- Fault Loaction (Fault bus)
- Relay Name
- Fault Type
- |Ia| (A)
- ∠ Ia (deg)
- |Ib| (A)
- ∠ Ib (deg)
- |Ic| (A)
- ∠ Ic (deg)
- |Va|
- ∠ Va
- |Vb|
- ∠ Vb
- |Vc|
- ∠ Vc
- 3*|I0|
- ∠ I0
1 | R1 | TPH_R1 | 2163.90 | -47.351 | 2163.90 | -167.35 | 2163.90 | 72.6486 | 0.92238 | -44.907 | 0.92238 | -164.91 | 0.92238 | 75.0927 | 0 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | R2 | TPH_R1 | 7.4E-12 | 0 | 7.4E-12 | 0 | 7.4E-12 | 0 | 0.90096 | -47.351 | 0.90096 | -167.35 | 0.90096 | 72.6486 | 0 | 0 |
1 | R3 | TPH_R1 | 7.2E-12 | 0 | 7.2E-12 | 0 | 7.2E-12 | 0 | 0.90096 | -47.351 | 0.90096 | -167.35 | 0.90096 | 72.6486 | 0 | 0 |
2) Simulate and Import from OpenDSS
2) 從 OpenDSS 模擬並匯入
The fault analysis information can be obtained from OpenDSS directly using the COM interface using the code below. The code simulates the necessary faults in OpenDSS and collects the fault currents observed by each device in the system for each fault.
故障分析資訊可以直接使用 COM 介面從 OpenDSS 獲得,使用以下代碼。該代碼在 OpenDSS 中模擬必要的故障,並收集系統中每個裝置對每個故障觀察到的故障電流。
Buses = SysInfo['Buses']
# %% collect fault Data
faultBuses = [x['Name'] for x in Buses]
faultBusPhases = [None]*len(faultBuses)
for ii in range(len(faultBuses)):
faultBusPhases[ii] = Buses[RSO_pack.index_dict(Buses,'Name',faultBuses[ii])]['nodes']
Fres = ['0.001','1']
Fts = ['3ph','SLG','LL']
FData = RSO_pack.getFaultInfo(dssCircuit,dssText,faultBuses,faultBusPhases,Fres,Fts,devLines,devNames,dev_BusV)
Fault_File_loc = pwd+'FData.csv'
FData.to_csv(Fault_File_loc,index=False,header=False)
Fault_Data_CSV = RSO_pack.read_Fault_CSV_Data(Fault_File_loc)
3) Import from RONM
3) 從 RONM 匯入
The fault information for each timestep should be included in the RONM output under the "Fault currents" section.
The section must contain an entry for each fault and the voltages and currents observed by each device for the faults.
Each device entry must contain the following:
1. |V| (V) : Voltage magnitude
2. phi (deg) : Voltage angle
3. |I| (A) : Current magnitude
4. theta (def): Voltage angle
5. |I0| (A) : Zero sequence current
6. |I1| (A) : Positive sequence current
7. |I2| (A) : Negative sequence current
每個時間步的故障資訊應包含在 RONM 輸出中的「故障電流」部分。該部分必須為每個故障包含一個條目,以及每個設備觀察到的電壓和電流。每個設備條目必須包含以下內容:1. |V| (V):電壓大小 2. phi (度):電壓角度 3. |I| (A):電流大小 4. theta (度):電壓角度 5. |I0| (A):零序電流 6. |I1| (A):正序電流 7. |I2| (A):負序電流
The following code can be used to read the fault analysis data from the RONM output.
# collect Fault Data
faultBuses = list(jsonDict['Fault currents'][1].keys())
faultBusesLOC = faultBuses
faultBusPhases = [None]*len(faultBuses)
for ii in range(len(faultBuses)):
faultBusPhases[ii] = Buses[RSO_pack.index_dict(Buses,'Name',faultBuses[ii])]['nodes']
Fault_Data_CSV = RSO_pack.getRONMFaultData(Ts, faultBuses, devTypes, devNames, devLines, dev_BusV, jsonDict['Fault currents'][Ts])
The primary function used to calculate the protection settings is "runSettingsOptimizer." The function calculates the optimized relay settings using the supplied network, steady-state, and fault data. The function also has some additional options and inputs outlined below.
用於計算保護設定的主要函數是「runSettingsOptimizer」。該函數使用提供的網路、穩態和故障數據計算最佳化的繼電器設定。該函數還有一些額外的選項和輸入,詳情如下。
- Main_dir: The main directory containing the "RSO_pack" folder and the files used to import the network, steady-state, and fault data.
Main_dir:包含「RSO_pack」資料夾及用於導入網路、穩態和故障數據的檔案的主要目錄。 - switchStates: switch states for each switch in the system (1: Closed, 0: Open)
switchStates:系統中每個開關的開關狀態 (1:關閉,0:打開) - switchLines: Name of lines with switches
開關線路:帶有開關的線路名稱 - Device_Data_CSV: Formatted steady-state data
裝置數據 CSV:格式化的穩態數據 - Fault_Data_CSV: Formatted fault data
故障數據 CSV:格式化的故障數據 - Fault_Res: Faut resistance as a list in increasing order (Example: ['R0_1', 'R1'])
故障電阻:以遞增順序列出的故障電阻(範例:['R0_1', 'R1']) - SysInfo: Formated system inforamtion
系統資訊:格式化的系統資訊 - Substation_bus: Main substation (used to determine the start of the system)
變電所匯流排:主變電所(用於確定系統的起始點) - Min_Ip: Minimum allowable pick value in primary amps
Min_Ip: 主要安培中允許的最小選擇值 - enableIT: True - Allow instantaneous trip if applicable, False - Disable instantaneous trip
enableIT: 真 - 允許瞬時跳脫(如適用),假 - 禁用瞬時跳脫 - Force_NOIBR: True - Force optimizer to ignore the distributed generation and nondirectional output settings; false - calculate directional overcurrent settings.
Force_NOIBR: 真 - 強制優化器忽略分散式發電和非定向輸出設置;假 - 計算定向過電流設置。 - CTI: Desired coordiantion time interval
CTI: 所需的協調時間間隔 - OTMax: Maximum allowable operating Time in seconds
OTMax: 允許的最大操作時間(秒) - type_select: Enable relay type selection
type_select: 啟用繼電器類型選擇 - SetDir: Output directional setting
SetDir: 輸出方向設定 - Sho_Plots: Enable plotting of system layout and optimization process
Sho_Plots: 啟用系統佈局和優化過程的繪圖 - GA_initial_seed: Optional input to initialize the optimization with predetermined values
GA_initial_seed: 可選輸入,用於以預定值初始化優化
settings,old_info = RSO_pack.runSettingsOptimizer(Main_dir,
switchStates,
switchLines,
Device_Data_CSV,
Fault_Data_CSV,
Fault_Res,
SysInfo,
Substation_bus,
Min_Ip,
enableIT,
Force_NOIBR,
CTI,
OTmax,
type_select,
SetDir,
Sho_Plots,
GA_initial_seed=initpop)
The Protection settings optimizer can be used with CAPE. PSS CAPE can be used to output device information and fault analysis needed by PSO as "CSV" files. The device status information file must contain a list of devices with their steady-state voltages, currents, and breaker status. An example file named "outputV1_624.csv" is provided, showing the data format required. An example fault data file named "fault_report_624.csv," which contains the fault analysis, is also provided as part of the example. A system information file containing the system configuration, layout, Bus information, Line information, transformer information, protection device information, and generation resource information is required. An example system information file named "IEEE123_Sysinfo.json" containing information for the IEEE 123 system is provided as part of the example. To run the setting optimizer using the data obtained from PSS@CAPE run the "CAPE_Example.py"
保護設定優化器可以與 CAPE 一起使用。PSS CAPE 可用於輸出設備資訊和 PSO 所需的故障分析,格式為 "CSV" 檔案。設備狀態資訊檔必須包含設備的穩態電壓、電流和斷路器狀態的清單。提供了一個名為 "outputV1_624.csv" 的範例檔,顯示所需的數據格式。還提供了一個名為 "fault_report_624.csv" 的範例故障數據檔,其中包含故障分析。需要一個系統資訊檔,該檔案包含系統配置、佈局、匯流排資訊、線路資訊、變壓器資訊、保護設備資訊和發電資源資訊。提供了一個名為 "IEEE123_Sysinfo.json" 的範例系統資訊檔,該檔案包含 IEEE 123 系統的資訊。要使用從 PSS@CAPE 獲得的數據運行設定優化器,請運行 "CAPE_Example.py"。
The Protection settings optimizer contains the code required to connect to OpenDSS and retrieve all necessary information to calculate relay settings. PSO utilizes the OpenDSS COM interface to obtain the required system information. PSO can also use a compiled and solved case to obtain the necessary device information and perform the fault analysis. An example integration with OpenDSS is provided in "Opendss_Example.py." This example will start OpenDSS compile the IEEE34bus system, solve the power flow and perform fault analysis to collect required device information for the optimization process.
保護設定優化器 (Protection settings optimizer) 包含連接到 OpenDSS 所需的程式碼,以檢索計算繼電器設定所需的所有資訊。PSO 利用 OpenDSS COM 介面來獲取所需的系統資訊。PSO 也可以使用已編譯和解決的案例來獲取必要的設備資訊並執行故障分析。範例整合 OpenDSS 的程式碼在 "Opendss_Example.py" 中提供。此範例將啟動 OpenDSS,編譯 IEEE34bus 系統,解決電力流並執行故障分析,以收集優化過程所需的設備資訊。
Resilient Operation of Networked Microgrids (RONM) uses "PowerModelsONM," an optimization library for operating and restoring electric power distribution feeders featuring networked microgrids. PowerModelsONM can be configured to output the necessary information to run the PSO. The outputs from the PowerModelsONM can be configured to output the system information, device information, and fault studies. The outputs are read by the PSO and used to calculate relay settings for each state the grid transitions through over the entire timeframe in the RONM output. An example integration with RONM output can be run using the "RONM_Example.py."
網絡微電網的韌性運行 (Resilient Operation of Networked Microgrids, RONM) 使用「PowerModelsONM」,這是一個用於操作和恢復電力配電線路的優化庫,特別針對網絡微電網。PowerModelsONM 可以配置為輸出運行 PSO 所需的信息。PowerModelsONM 的輸出可以配置為輸出系統信息、設備信息和故障研究。這些輸出由 PSO 讀取,並用於計算在 RONM 輸出整個時間範圍內,電網過渡到每個狀態的繼電器設置。可以使用「RONM_Example.py」運行與 RONM 輸出的示例集成。