Расчёт установившегося режима со случайным изменением параметров — различия между версиями

Материал из Wiki Power System
Перейти к: навигация, поиск
м (Описание расчётов)
Строка 33: Строка 33:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Функция для случайного изменения одного параметра линии электропередач ==
+
== Функция для случайного изменения одного параметра ==
  
 
<syntaxhighlight lang="python" >
 
<syntaxhighlight lang="python" >
 
def calcRandomSingleParam_Line(stbNet,rndNet,sigma,nameParam):
 
def calcRandomSingleParam_Line(stbNet,rndNet,sigma,nameParam):
 
     #Функция, которая вносит случайные возмущения в параметры ЛЭП, по нормальному закону
 
     #Функция, которая вносит случайные возмущения в параметры ЛЭП, по нормальному закону
 +
    calcTableParam(stbNet.line,rndNet.line,sigma,nameParam)
 +
</syntaxhighlight>
 +
 +
<syntaxhighlight lang="python" >
 +
def calcRandomSingleParam_Load(stbNet,rndNet,sigma,nameParam):
 +
    #Функция, которая вносит случайные возмущения в параметры нагрузки, по нормальному закону
 +
    calcTableParam(stbNet.load,rndNet.load,sigma,nameParam)
 +
</syntaxhighlight>
 +
 +
<syntaxhighlight lang="python" >
 +
def calcRandomSingleParam_extGrid(stbNet,rndNet,sigma,nameParam):
 +
    #Функция, которая вносит случайные возмущения в параметры внешней сети, по нормальному закону
 +
    calcTableParam(stbNet.ext_grid,rndNet.ext_grid,sigma,nameParam)
 +
</syntaxhighlight>
 +
 +
<syntaxhighlight lang="python" >
 +
def calcTableParam(stbTable,rndTable,sigma,nameParam):
 
     j=0
 
     j=0
     for r in stbNet.line[nameParam]:
+
     for r in stbTable[nameParam]:      
         #Генерируем случайный, нормально рапсределённый параметр
+
         #Генерируем случайный, нормально распределённый параметр
         k=np.random.normal(r, sigma*r)      
+
         k=np.random.normal(r, sigma*r)
         rndNet.line[nameParam].iloc[j]=k
+
         rndTable[nameParam].iloc[j]=k
 
         j=j+1
 
         j=j+1
 
</syntaxhighlight>
 
</syntaxhighlight>
Строка 49: Строка 66:
  
 
<syntaxhighlight lang="python" >
 
<syntaxhighlight lang="python" >
def calcSingleStadyState(inNet,copyNet,lineCases):
+
def calcSingleStadyState(inNet,copyNet,lineCases,loadCases,extGridCases):
 
     #Функция выполняет расчёт одного режима со случайными парамтерами         
 
     #Функция выполняет расчёт одного режима со случайными парамтерами         
 
     #В переменной lineCases содердится информация о случайно изменяемых параметрах
 
     #В переменной lineCases содердится информация о случайно изменяемых параметрах
Строка 56: Строка 73:
 
     for sigma, nameParam in lineCases:
 
     for sigma, nameParam in lineCases:
 
         calcRandomSingleParam_Line(inNet,copyNet,sigma,nameParam)
 
         calcRandomSingleParam_Line(inNet,copyNet,sigma,nameParam)
 +
    for sigma, nameParam in loadCases:
 +
        calcRandomSingleParam_Load(inNet,copyNet,sigma,nameParam)
 +
    for sigma, nameParam in extGridCases:
 +
        calcRandomSingleParam_extGrid(inNet,copyNet,sigma,nameParam)
 
     #Расчёт режима
 
     #Расчёт режима
 
     calcRgm = 1
 
     calcRgm = 1
Строка 68: Строка 89:
  
 
<syntaxhighlight lang="python" >
 
<syntaxhighlight lang="python" >
def calcManyStadyState(inNet,nameinNet,casesLine,runs):
+
def calcManyStadyState(inNet,nameinNet,lineCases,loadCases,extGridCases,runs):
 
     #Результаты расчётов по узлам
 
     #Результаты расчётов по узлам
 
     col = ['numRun','numBus','vm_pu', 'va_degree', 'p_kw', 'q_kvar']
 
     col = ['numRun','numBus','vm_pu', 'va_degree', 'p_kw', 'q_kvar']
Строка 87: Строка 108:
 
     copyInNet = copy.deepcopy(inNet)
 
     copyInNet = copy.deepcopy(inNet)
 
     for i in range(runs):
 
     for i in range(runs):
         calcRgm, copyInNet = calcSingleStadyState(inNet,copyInNet,lineCases)
+
         calcRgm, copyInNet = calcSingleStadyState(inNet,copyInNet,lineCases,loadCases,extGridCases)
 
         if calcRgm==1:
 
         if calcRgm==1:
 
             rgm += 1
 
             rgm += 1
Строка 101: Строка 122:
 
     #Отчёт о проделанной работе
 
     #Отчёт о проделанной работе
 
     print('Отчёт по результатам расчётов сети ',nameNet,'.')
 
     print('Отчёт по результатам расчётов сети ',nameNet,'.')
     print ('  - Режимов успешно расчитано -',str(rgm), 'из',str(runs),'расчётов.')
+
     print ('  - Режимов успешно рассчитано -',str(rgm), 'из',str(runs),'расчётов.')
 
     return resBus, resLine
 
     return resBus, resLine
 
</syntaxhighlight>
 
</syntaxhighlight>
Строка 121: Строка 142:
 
         (0.05,'x_ohm_per_km'),         
 
         (0.05,'x_ohm_per_km'),         
 
     ]
 
     ]
 
+
#Изменения в узлах нагрузки
 +
loadCases = [
 +
        (0.05,'const_i_percent'),
 +
        (0.05,'const_z_percent'),       
 +
    ]
 +
#Колебания внешней сети
 +
extGridCases = [
 +
        (0.01,'vm_pu'),       
 +
    ]
 
#Количество расчётов
 
#Количество расчётов
 
runs = 10
 
runs = 10
Строка 133: Строка 162:
 
#Расчёты режимов
 
#Расчёты режимов
 
for net, nameNet in netCases:
 
for net, nameNet in netCases:
     resBus, resLine = calcManyStadyState(net,nameNet,lineCases,runs)
+
     resBus, resLine = calcManyStadyState(net,nameNet,lineCases,loadCases,extGridCases,runs)
 
     resBus['Сеть']=nameNet
 
     resBus['Сеть']=nameNet
 
     resLine['Сеть']=nameNet
 
     resLine['Сеть']=nameNet

Версия 20:07, 15 декабря 2018

Данная статья посвящена описанию примера реализации метода Монте-Карло для оценки статистических законов изменения параметров установившегося режима, при случайной вариации, по заранее заданному закону, исходных данных.

Описание расчётов

Значения перетоков активной мощности используются для соблюдения требований к устойчивости энергосистем при планировании и управлении электроэнергетическим режимом. Величины перетоков активной мощности зависят как от мощностей нагрузок в узлах сети, так и от параметров электрической сети. При создании математической модели исследуемой сети используется ряд допущений, например, мощность нагрузки задается конкретным числом на отдельных интервалах времени, хотя в действительности она не является постоянной величиной и может быть представлена некоторым интервалом, внутри которого находятся фактические значения. Параметры сети так же изменяются во времени под влиянием различных факторов, и их задание в виде постоянных величин вводит погрешность в расчеты исследуемой сети. В частности, величина предельного перетока обратно пропорциональна сопротивлению рассматриваемой линии.

Оценка влияния колебаний нагрузок и изменения сопротивлений линий на изменение величины предельного перетока, а также оценка интервала его возможных значений может представлять интерес для дальнейшего использования величины предельного перетока в инженерных расчетах.

В настоящей статье предлагается применить на практике метод Монте Карло (метод статических испытаний). Это численный метод, основанный на моделировании случайных величин и построении статистических оценок для искомых величин. Изменения нагрузки энергосистемы представляют собой суммирование изменений нагрузок отдельных электроприемников. Основное допущение состоит в том, что все одиночные элетроприемники подключаются и отключаются независимо друг от друга. Как известно, независимое сложение достаточно большого числа случайных слагаемых приводит к нормальному распределению вероятности их суммы [1].

Описание мощностей нагрузок нормальным распределением дает возможность решения задач достоверизации и обобщения результатов косвенной статистической оценки вероятностных характеристик колебаний небаланса мощности энергосистем и обменной мощности их объединения.

Предлагаемый метод основан на проведении серий расчетов установившихся режимов при случайном изменении величин мощностей в узлах нагрузок сети, при случайном изменении величин сопротивлений линий или при сочетании этих изменений. С помощью ЭВМ моделируется вероятностный характер заданных величин. В этом случае случайная величина (мощность нагрузки каждого узла, сопротивление линии или их сочетание) задается законом распределения, а именно возможные значения случайной величины сопоставляются с вероятностями их появления. В качестве диапазона вариации параметров можно ориентироваться на величины приведённые здесь.

Расчёты установившихся режимов проводятся с использованием библиотеки pandapower.

Импорт необходимых для расчёта библиотек

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import copy

import pandas as pd
import pandapower as pp
import pandapower.networks as pn

#Настройки отрисовки графиков
sns.set(style="whitegrid")
plt.rcParams['figure.figsize'] = (14, 6)

Функция для случайного изменения одного параметра

def calcRandomSingleParam_Line(stbNet,rndNet,sigma,nameParam):
    #Функция, которая вносит случайные возмущения в параметры ЛЭП, по нормальному закону
    calcTableParam(stbNet.line,rndNet.line,sigma,nameParam)
def calcRandomSingleParam_Load(stbNet,rndNet,sigma,nameParam):
    #Функция, которая вносит случайные возмущения в параметры нагрузки, по нормальному закону
    calcTableParam(stbNet.load,rndNet.load,sigma,nameParam)
def calcRandomSingleParam_extGrid(stbNet,rndNet,sigma,nameParam):
    #Функция, которая вносит случайные возмущения в параметры внешней сети, по нормальному закону
    calcTableParam(stbNet.ext_grid,rndNet.ext_grid,sigma,nameParam)
def calcTableParam(stbTable,rndTable,sigma,nameParam):
    j=0
    for r in stbTable[nameParam]:        
        #Генерируем случайный, нормально распределённый параметр
        k=np.random.normal(r, sigma*r)
        rndTable[nameParam].iloc[j]=k
        j=j+1

Функция для расчёта единичного установившегося режима

def calcSingleStadyState(inNet,copyNet,lineCases,loadCases,extGridCases):
    #Функция выполняет расчёт одного режима со случайными парамтерами        
    #В переменной lineCases содердится информация о случайно изменяемых параметрах
    
    #Расчёт случайных изменений парметров схемы
    for sigma, nameParam in lineCases:
        calcRandomSingleParam_Line(inNet,copyNet,sigma,nameParam)
    for sigma, nameParam in loadCases:
        calcRandomSingleParam_Load(inNet,copyNet,sigma,nameParam)
    for sigma, nameParam in extGridCases:
        calcRandomSingleParam_extGrid(inNet,copyNet,sigma,nameParam)
    #Расчёт режима
    calcRgm = 1
    try:
        pp.runpp(net=copyNet, max_iteration=100)
    except Exception:
        calcRgm=0
    return calcRgm,copyNet

Функция расчёта множества режима со случайными параметрами

def calcManyStadyState(inNet,nameinNet,lineCases,loadCases,extGridCases,runs):
    #Результаты расчётов по узлам
    col = ['numRun','numBus','vm_pu', 'va_degree', 'p_kw', 'q_kvar']
    resBus = pd.DataFrame(columns=col)
    col = ['numRun','numLine','p_from_kw', 'q_from_kvar', 'p_to_kw', 'q_to_kvar', 'pl_kw', 'ql_kvar',
           'i_from_ka', 'i_to_ka', 'i_ka', 'loading_percent']
    resLine = pd.DataFrame(columns=col) 

    #Массив номеров узлов
    numBuses= [i for i in range(0,inNet.bus.iloc[:,0].size)]
    #Массив номеров линий
    numLines= [i for i in range(0,inNet.line.iloc[:,0].size)]
    
    #Количество успешных расчётов режима
    rgm = 0
    #Копирование исходной сети в новую область памяти, для того чтобы не изменять исходную сеть.
    #В исходной сети будут храниться мат. ожидания параметров
    copyInNet = copy.deepcopy(inNet)
    for i in range(runs):
        calcRgm, copyInNet = calcSingleStadyState(inNet,copyInNet,lineCases,loadCases,extGridCases)
        if calcRgm==1:
            rgm += 1
            #Сохранение результатов расчётов
            #По узлам
            copyInNet.res_bus['numRun']=i
            copyInNet.res_bus['numBus']=numBuses
            resBus= pd.merge(resBus, copyInNet.res_bus,  how = 'outer')
            #По линиям
            copyInNet.res_line['numRun']=i
            copyInNet.res_line['numLine']=numLines
            resLine= pd.merge(resLine, copyInNet.res_line,  how = 'outer')
    #Отчёт о проделанной работе
    print('Отчёт по результатам расчётов сети ',nameNet,'.')
    print ('   - Режимов успешно рассчитано -',str(rgm), 'из',str(runs),'расчётов.')
    return resBus, resLine

Скрипт для инициализации и запуска расчётов

#Рассматриваемые сети
netCases = [
    (pn.case14(),'14 IEEE'),
    (pn.case33bw(),'33bw IEEE'),
    (pn.case118(),'118 IEEE'),
]

#Случайно изменяемые параметры в таблице ветви
#(дисперсия задаётся как доля от мат. ожидания параметра (при 1 - дисперсия = 100%), названием параметра)
lineCases = [
        (0.05,'r_ohm_per_km'),
        (0.05,'x_ohm_per_km'),        
    ]
#Изменения в узлах нагрузки
loadCases = [
        (0.05,'const_i_percent'),
        (0.05,'const_z_percent'),        
    ]
#Колебания внешней сети
extGridCases = [
        (0.01,'vm_pu'),        
    ]
#Количество расчётов
runs = 10

#Создание шаблона таблицы для хранения результатов
allResBus = pd.DataFrame(columns=['Сеть','numRun','numBus',
                               'vm_pu', 'va_degree', 'p_kw', 'q_kvar'])
allResLine = pd.DataFrame(columns=['Сеть','numRun','numLine',
                                'p_from_kw', 'q_from_kvar', 'p_to_kw', 'q_to_kvar', 'pl_kw', 'ql_kvar',
                                'i_from_ka', 'i_to_ka', 'i_ka', 'loading_percent'])
#Расчёты режимов
for net, nameNet in netCases:
    resBus, resLine = calcManyStadyState(net,nameNet,lineCases,loadCases,extGridCases,runs)
    resBus['Сеть']=nameNet
    resLine['Сеть']=nameNet
    allResBus = pd.merge(allResBus, resBus,  how = 'outer')
    allResLine = pd.merge(allResLine, resLine,  how = 'outer')

Результаты расчётов

Были получены результаты перетоков активной и реактивной мощности линии для каждого успешно рассчитанного установившегося режима (без нарушения статической устойчивости). По полученным значениям мощностей были построены их распределения и определены диапазоны изменения.

Файлы для скачивания

  1. Kolmogorov A.N. Sur la loi forte des grands nombres / A.N. Kolmogorov // C. R. Acad. Sci. Paris. - 1930. - Vol. 191. - P.910-912.