Разработка макроса для расчета коэффициентов эффективности влияния нагрузок станций на перетоки в сечениях www.inorxl.com В этом примере мы разберем достаточно сложный, но полезный макрос для расчета коэффициентов эффективности влияния нагрузки станций на перетоки в сечениях. Я постарался сделать этот материал доступным как для тех, кто не имеет опыта в работе режимщика, так и для тех, кто пока не владеет приемами программирования. Если Вам покажется, что речь идет о чемто очевидном, можете пропустить раздел и перейти к следующему. Что такое сечение и эффективности ? для чего нужны коэффициенты При планировании и управлении режимами энергосистемы приходится учитывать массу ограничений. Во-первых, это технологические ограничения оборудования: диапазоны изменения активной и реактивной мощности генераторов и компенсирующих устройств, пропускная способность линий электропередач, нагрузочная способность трансформаторов и т.д. В дополнение к ограничениям оборудования существует большая группа ограничений, связанных с устойчивостью синхронной работы энергосистемы в целом. Эксплуатационные границы устойчивого режима задаются ограничениями перетоков между районами энергосистемы. При превышении допустимых перетоков надежность режима снижается, и под действием даже незначительных возмущений в энергосистеме может возникнуть асинхронный ход, ликвидация которого может потребовать размыкания сети, ограничения потребления, экстренного останова генераторов или проведения подобных нежелательных мероприятий. Поэтому при планировании и ведении режима постоянно требуется контролировать допустимость перетоков. Чтобы упростить эту задачу обычно выделяют некоторую группу линий, связывающих районы, и объединяют их в так называемое сечение. Переток мощности в сечении равен сумме потоков входящих в него линий. Такая группировка упрощает задание ограничений при планировании и делает оперативные схемы более наглядными, поскольку не нужно контролировать или наносить на схеме потоки по отдельным линиям. Сечение имеет положительное направление, условно принимаемое от района начала к району конца. Сечение называется изолирующим, если при размыкании всех линий, которые в него входят, система разделится на две синхронные зоны. Положительный переток называют прямым, отрицательный – обратным. На прямой и обратный перетоки накладывают ограничения по активной мощности. Если текущий переток находится в заданных пределах – режим энергосистемы допустим, если нет – необходимо провести мероприятия по вводу перетока в допустимые ограничения. Остается ответить на вопрос – как удержать переток в сечении в допустимых пределах ? Если сечение изолирующее – ответ очевиден: нужно изменить генерацию в районах на величину нарушения. Например, чтобы снизить переток – нужно уменьшить генерацию в районе начала и увеличить в районе конца сечения. Однако если районы связаны несколькими сечениями, нужно сделать такие изменения генерации, чтобы ограничения по всем сечениям остались в заданных пределах. Для решения этой задачи, конечно, существуют специальные программы оптимизации, которые используются при планировании. Но для оперативной работы часто применяют более простой и хотя менее точный, но эффективный метод – заранее определить зависимость между мощностью каждого управляемого генератора и перетоком в сечениях. Зная эти зависимости можно определить оптимальную комбинацию изменения генерации для ввода перетоков в заданные ограничения. Зависимость задается в виде коэффициента эффективности, равного Δ𝑃сеч𝑖 𝐾эфф𝑖𝑗 = Δ𝑃ст𝑗 где Δ𝑃сеч𝑖 – изменение перетока по -му сечению, Δ𝑃ст𝑗 – изменение мощности 𝑗-ой станции. Чтобы вычислить этот коэффициент для заданной схемы нужно зафиксировать текущие значения перетоков по сечениям и значения генерации. Затем по некоторому генератору ввести приращение мощности генерации и рассчитать установившийся режим. Перетоки в сечениях изменятся. Если изменения перетоков по сечениям разделить на заданное приращение мощности, получим коэффициенты по всем сечениям относительно выбранного генератора. Зная эти коэффициенты по всем сечениям относительно всех генераторов можно оперативно находить наиболее эффективные комбинации генераторов для ввода перетоков сечений в заданные пределы. Если в схеме, для которой рассчитана матрица коэффициентов эффективности, выполнить переключения, матрица, в общем случае, уже не будет адекватно описывать зависимости перетоков от генерации. Поэтому матрицы рассчитываются для всех ремонтных схем, в которых отключены какие либо элементы сети. Безусловно, некоторые ремонтные схемы будут иметь похожие матрицы, но для того, чтобы в этом убедиться, все равно нужно провести расчеты. Для 𝑛 ремонтных схем с 𝑚 генераторов нужно провести 2𝑚𝑛 расчетов, учитывая, что отдельно нужно рассматривать как положительные, так и отрицательные приращения генерации каждой станции. В ручном режиме такая работа займет существенное время, поэтому стоит один раз поработать над макросом для автоматизации расчетов. Исходные данные Макрос будет использовать: • • • • Исходную схему. Список сечений. Список ветвей, отключение каждой из которых создает ремонтную схему. Список генераторных узлов с указанием значений приращений мощности. Исходная схема хранится в таблицах Excel как обычно. Сечения легко задать на отдельной вкладке в виде таблицы. В таблице должны быть колонки с номером сечения, его названием и формулой для каждого сечения. Формула определяет способ расчета перетока. В простейшем случае это просто сумма потоков по входящим в сечение ветвям. Самым простым и удобным способом задать ветви, отключения которых определяют ремонтные схемы, является ввод колонки «Схема» в таблицу «Ветви», в которой единица отмечает ветвь из списка. Макрос пройдет по колонке и определит список отключаемых ветвей. Пользователю будет удобно отмечать ветви прямо в таблице ветвей. Таким же приемом можно воспользоваться и для списка узлов. В таблице «Узлы» введем колонку «DeltaP». Для тех генераторов, которые должны участвовать в регулировании перетоков в сечениях, в колонке укажем величину приращения мощности. Нулевое значение в колонке указывает на то, что генератор не учитывается при расчете коэффициентов эффективности. Макрос сможет построить список генераторов и заодно выяснить, как нужно изменять их мощность. Требуемая форма отображения результатов работы Форма, в которой должны быть представлены коэффициенты эффективности, регламентирована отраслевыми типовыми положениями по управлению режимами: № Контролируемое сечение Схема сети Наименование электростанции Коэффициент эффективности Примечание В колонке «№» указывают порядковый номер сечения. В колонке «Схема сети» – название ремонтной схемы. Макрос будет вносить в эту колонку название отключенной ветви. В колонке «Наименование электростанции» указывается название узла, в котором макрос задал приращение мощности. В колонке «Примечание» макрос будет выводить тип изменения: «Разгрузка» или «Загрузка» с указанием величины. В процессе расчетов может возникнуть ситуация, в которой установившийся режим после ввода изменений не сбалансируется. В этом случае в колонке «Примечание» макрос выведет «УР не существует». Особенности реализации В работе макроса предусмотрено отключение ветвей. При расчете УР выполняется предварительный контроль схемы, при котором топология сети может измениться независимо от «намерений» макроса. Например, если отключены все ветви, подходящие к некоторому узлу, узел будет отключен. Макрос должен будет включить этот узел при переходе к следующей ремонтной схеме, иначе ветви, подходящие к этому узлу будут отключены все тем же контролем схемы. Эта проблема просто решается путем запоминания исходных состояний узлов и ветвей перед началом перебора ремонтных схем. Исходные состояния копируются во временные колонки в таблицах «Узлы» и «Ветви». Схема до начала работы макроса считается нормальной (все основные элементы сети включены, допустимы нормально отключенные элементы). Ремонтные схемы будут строиться на ее базе путем отключения выбранных ветвей. После того, как работа с некоторой текущей ремонтной схемой закончена, состояния узлов и ветвей приводятся в соответствие с нормальной схемой (копируются из исходных состояний, запомненных во временных колонках). Для того чтобы перейти к следующей ремонтной схеме, достаточно отключить следующую отмеченную ветвь. При задании отключаемых ветвей необходимо следить за тем, чтобы балансирующий узел схемы не отключался ни в одной ремонтной схеме. Если балансирующий узел будет отключен, для всей ремонтной схемы расчет коэффициентов будет невозможен. Алгоритм работы макроса Алгоритм сначала приведем на псевдоязыке Запомнить состояния узлов и ветвей в нормальной схеме Цикл по ветвям | Если ветвь отмечена | | Отключить ветвь | | Рассчитать УР и запомнить перетоки по сечениям | | Цикл по узлам | | | Если для узла задано приращение | | | | Ввести в узел положительное приращение и рассчитать УР | | | | Цикл по сечениям | | | | | Рассчитать коэффициент и заполнить строку таблицы коэффициентов | | | | Конец цикла по сечениям | | | | Ввести в узел отрицательное приращение и рассчитать УР | | | | Цикл по сечениям | | | | | Рассчитать коэффициент и заполнить строку таблицы коэффициентов | | | | Конец цикла по сечениям | | | | Восстановить исходную генерацию в узле | | | Конец Если | | Конец цикла по узлам | | Восстановить запомненные состояния узлов и ветвей нормальной схемы | Конец Если Конец цикла по ветвям Алгоритм построен так, чтобы количество расчетов режима было минимальным. Для этого расчет коэффициентов по всем сечениям выполняется во внутреннем цикле по единой расчетной схеме. Расчетная схема строится путем отключения одной из выбранных ветвей и ввода приращения по выбранному узлу. Также алгоритм учитывает нюансы обработки топологии схемы, рассмотренные в предыдущем разделе. Реализован алгоритм на встроенном в Excel Visual Basic for Applications – VBA. Порядок подключения расчетного модуля InorXL к макросу подробно рассмотрен в руководстве пользователя. При разработке макроса, в первую очередь, ставилась цель сделать его текст понятным, поэтому часть логики, необходимой для обработки ошибок не реализована. Например, макрос будет выдавать ошибку при отсутствии заданных сечений. Поля адресуются по номерам столбцов, что сделает макрос неработоспособным при изменении макета страницы. Макрос не делает никакого форматирования получаемой таблицы. Но при желании можно довести этот макрос до «промышленного» уровня. Далее приведен текст макроса с комментариями, раскрывающими технические подробности реализации. Готовый файл Excel с макросом, работающим на схеме IEEE-14, приложен к этому описанию. Вы можете запустить макрос и на своей схеме. Для этого нужно вставить столбец «М» c названием «DeltaP» на вкладке «Узлы» и ввести для требуемых узлов значения приращений в МВт. На вкладке «Ветви» нужно вставить столбец «D» под названием «Схема» и отметить символом «1» все ветви, отключение которых создает ремонтные схемы. Далее нужно создать вкладку «Сечения», на которой сформировать набор сечений в таблице вида: № Название P В столбце «P» нужно задать формулы для расчета перетоков по сечениям. Примерный вид формулы «=Ветви!Q2+Ветви!Q6+Ветви!Q4+Ветви!Q5». Эта формула рассчитывает переток в сечении в виде суммы потоков по ветвям в строках 2,4,5 и 6 таблицы «Ветви». Складываются значения полей «Pнач», которые находятся в столбце «Q». В столбцах «№» и «Название» нужно задать соответствующие описания сечений. И наконец, нужно создать вкладку «Коэффициенты». В первой строке таблицы на этой вкладке нужно создать заголовок: № сечения Название сечения Ремонтная схема Станция Коэффициент Примечание После запуска макроса эта таблица будет заполнена. Текст макроса ' Макрос расчета коэффициентов эффективности влияния изменения нагрузки станций на переток в сечении Sub Коэффициенты_эффективности() ' объявляем и инициализируем объект InorXL Dim spInor As InorXLAddin Set spInor = Application.COMAddIns("InorXL.InorXLAddin.1").Object ' если объект InorXL доступен, продолжаем работу If Not spInor Is Nothing Then ' объявляем и инициализируем объекты таблиц ветвей, узлов, сечений и коэффициентов Dim PageCross, PageCoes, PageBranches, PageNodes As Worksheet Set PageCross = Application.ActiveWorkbook.Worksheets("Сечения") Set PageCoes = Application.ActiveWorkbook.Worksheets("Коэффициенты") Set PageBranches = Application.ActiveWorkbook.Worksheets("Ветви") Set PageNodes = Application.ActiveWorkbook.Worksheets("Узлы") ' начинаем заполнение таблицы коэффициентов со второй строки (в первой - заголовок) CoeTableCounter = 2 ' В процессе работы показываем таблицу коэффициентов PageCoes.Activate ' очищаем таблиц коэффициентов PageCoes.Range("A2").Select PageCoes.Range(Selection, ActiveCell.SpecialCells(xlLastCell)).Select Selection.ClearContents ' создаем дополнительные столбцы в таблицах узлов и ветвей для запоминания состояний в исходной схеме Call InsertStoreState(PageBranches) Call InsertStoreState(PageNodes) ' сохраняем состояния ветвей и узлов в исходной схеме (копируем из столбцов 6 (ветви) и ' 3 (узлы) в столбцы 30, созданные в двух вызовах функции InsertStoreState Call StoreState(PageBranches, 6) Call StoreState(PageNodes, 3) ' подсчитываем количество ветвей, которые образуют ремонтные схемы CrossBlockCount = 1 For j = 2 To LastRow(PageBranches) ' в цикле по ветвям проверяем, ести ли единица в столбце "схема". Если да ' то увеличиываем счетчик ремонтных схем на единицу. Признак подразумевается в столбце 4 If PageBranches.Cells(j, 4) <> "" Then CrossBlockCount = CrossBlockCount + 1 Next ' подсчитываем количество узлов, в которых будет изменяться нагрузка станций CheckNodesCount = 0 For j = 2 To LastRow(PageNodes) ' в цикле по узлам проверяем значение поля DeltaP и если оно ненулевое ' увеличиваем счетчик узлов на 2 ( разгрузка + загрузка ) ' Поле DeltaP должно находиться в столбце 13 If PageNodes.Cells(j, 13) <> "" Then CheckNodesCount = CheckNodesCount + 2 Next ' вычисляем размер блока строк для каждого сечения (количество_ремонтных_схем * количество_станций) CrossBlockCount = CrossBlockCount * CheckNodesCount ' перебираем ремонтные схемы For j = 1 To LastRow(PageBranches) ' номеру 1 соответствует нормальная схема If j = 1 Then BranchName = "Нормальная" BranchOnOff = "1" Else ' для номеров больше чем 1 формируем название ремонтной схемы по названию отключаемой ветви BranchOnOff = PageBranches.Cells(j, 4).Value BranchName = PageBranches.Cells(j, 5).Value End If ' если у ветви есть признак отключения (непустое значение в поле "Схема") If BranchOnOff <> "" Then ' отключаем эту ветвь If j > 1 Then PageBranches.Cells(j, 6).Value = "Откл" ' перебираем станции For g = 1 To LastRow(PageNodes) ' номеру 1 соответствует схема с исходными нагрузками станций If g = 1 Then ' для исходных нагрузок станций считаем УР и запоминаем перетоки по сечениям spInor.LF 1, 1 ' копируем перетоки по сечениям в соседний столбец For so = 2 To LastRow(PageCross) PageCross.Cells(so, 4).Value = PageCross.Cells(so, 3).Value Next Else DeltaP = PageNodes.Cells(g, 13) ' если для узла задано изменение нагрузки станции If DeltaP <> 0 Then ' для этого узла делаем два изменения - в плюс (загрузка) и в минус (разгрузка) For x = 0 To 1 Remark = "Загрузка" Mult = 1 If x = 0 Then Remark = "Разгрузка" Mult = -1 End If ' формируем комменатарий в виде названия действия и значения изменения нагрузки станции Remark = Remark + " " + CStr(DeltaP) ' запоминаем исходную генерацию в узле OldP = PageNodes.Cells(g, 14).Value ' изменяем генерацию в узле на заданное значение PageNodes.Cells(g, 14).Value = PageNodes.Cells(g, 14).Value + DeltaP * Mult Dim Code As InorNetStatus ' рассчитываем УР Code = spInor.LF(1, 1) ' если УР не балансируется, заменяем комментарий на "УР не существует" If (Code <> STATUS_OK) Then Remark = "УР не существует" ' восстанавливаем исходное значение генерации узла PageNodes.Cells(g, 14).Value = OldP ' перебираем сечения For s = 2 To LastRow(PageCross) CrossKey = PageCross.Cells(s, 1).Value CrossName = PageCross.Cells(s, 2).Value ' рассчитываем коэффициент, как частое от разности исходного перетока и перетока с измененной генерации ' и величины изменения нагрузки Coe = (PageCross.Cells(s, 3).Value - PageCross.Cells(s, 4)) / (DeltaP * Mult) ' рассчитываем номер строки, в которую будем выводит информацию по коэффициентам ' номер строки это порядковый номер комбинации ремонтной схемы и станции + ' номер_сечения * размер_блока_сечения NewPos = CoeTableCounter + (s - 2) * CrossBlockCount ' выводим стороку таблиы коэффициентов PageCoes.Cells(NewPos, 1).Value = CrossKey ' номер сечения PageCoes.Cells(NewPos, 2).Value = CrossName ' название сечения PageCoes.Cells(NewPos, 3).Value = BranchName ' название ремонтной схемы PageCoes.Cells(NewPos, 4).Value = PageNodes.Cells(g, 2).Value ' название станции PageCoes.Cells(NewPos, 5).Value = Coe ' значение коэффициента PageCoes.Cells(NewPos, 6).Value = Remark ' примечание Next ' переходим к следующей комбинации ремонтной схемы и станции CoeTableCounter = CoeTableCounter + 1 Next End If End If Next End If ' после завершения работы с ремонтной схемой, восстанавливаем нормальную схему Call ReStoreState(PageBranches, 6) Call ReStoreState(PageNodes, 3) Next Else MsgBox "InorXL не установлен" End If End Sub ' Процедура добавления столбца для хранения исходного состояния узла или ветви Sub InsertStoreState(ByVal ExPage As Worksheet) With ExPage If ExPage.Cells(1, 30).Value <> "ИсхСост" Then Cells(1, 30).Columns.Select Selection.Insert .Cells(1, 30).Value = "ИсхСост" End If End With End Sub ' Процедура сохранения исходного состояния узла или ветви Sub StoreState(ByVal ExPage As Worksheet, ColPos As Integer) With ExPage For i = 2 To LastRow(ExPage) .Cells(i, 30).Value = .Cells(i, ColPos).Value Next End With End Sub ' Процедура восстановления исходного состояния узла или ветви Sub ReStoreState(ByVal ExPage As Worksheet, ColPos As Integer) With ExPage For i = 2 To LastRow(ExPage) .Cells(i, ColPos).Value = .Cells(i, 30).Value Next End With End Sub ' Функция рассчета количества строк в таблице Function LastRow(Page) LastRow = Page.Range("A65536").End(xlUp).Row End Function