Это моя первая статья на хабре, потому что хотелось поделиться своим опытом объединения знаний из разных сфер, ну и в целом, рассказать, что вот и такое бывает.
Для начала вводная, я почти всю послеуниверситетскую жизнь работал в энергетике, а конкретно в службе релейной защиты в Ленэнерго. Но ближе к началу 22 года стал задумываться о вечном, ситуация стала ухудшаться и я, как тогда было «модно», тряхнул стариной (благо в школе и универе увлекался программированием) и начал вспоминать как кодить. Довольно быстро попал в коммерческую разработку, специализирующуюся на урбанистике и застройке, где успешно и работаю по сей день.
В определенный момент мне стало жалко, что столько лет накопленного опыта в энергетике улетают в трубу и я решил, что хорошо было бы объединить опыт, полученный в РЗА с опытом, полученным в разработке. Т.к. основной проект на работе был связан с генерацией застройки, работой с картами и алгоритмами генерации, я решил особо не мудрить и сделать что-то похожее, но связанное с подстанциями. В нашем проекте электрические сети были условными и шли из внешней границы территории, из тумана войны. И я подумал, в реальности ведь у нас нет волшебных питающих сетей – городские районы часто питаются через расположенные неподалёку понижающие подстанции. Поэтому хорошо было бы, чтобы пользователь, который задумал какое-то строительство, и который понимает какая мощность ему требуется, чтобы запитать новый район, мог с ходу за пару секунд сгенерировать несколько вариантов расстановки условной и усредненной типовой понижающей подстанции с основным оборудованием, с кабель-каналами, охранными зонами и необходимыми расчетами и прочими штуками, чтобы понимать реально ли это на данной территории и что ему для этого потребуется. Потребуется ли это в действительности меня не очень волновало, хотя я знал, что есть подобные программы для проектантов, но идея уже запустилась в мозге и просто так уже оставить было нельзя. К тому же получив схему подстанции, можно было реализовать другие функции для других сфер. Т.е. первое, что специалист по территориальному планированию мог бы быстро проверить, помещается ли подстанция на разных участках и заранее заметить проблемы. Второе, для сетевой компании или заказчика генератор мог бы быть полезен на стадии обсуждения технического присоединения. Например, чтобы сравнить несколько заранее заданных вариантов класса напряжения и типовой схемы, оценить требуемую площадь, ожидаемые токи КЗ и возможные ограничения по оборудованию. Ещё одно возможное применение (и наверное чуть-ли не главное) — это обучение. На готовой схеме можно показывать и объяснять, как расположение оборудования связано с электрической моделью, что меняется при включении секционного выключателя, откуда берутся токи короткого замыкания, почему для проверки защиты выбирается определённый режим и как первичная схема затем представляется в файле IEC 61850 SCL для каких-нибудь цифровых подстанций.
Вооружившись этим глобальным теоретическим планом, и большой долей энтузиазма, я пошел реализовывать структуру. Сразу забегу вперед и оставлю здесь как это выглядит сейчас, чтобы визуально лучше представлять, что к чему.
Сразу оговорюсь: это исследовательский прототип для концептуальной (демо) стадии, а не система рабочего проектирования и не сертифицированный расчётный комплекс, как может казаться. Генератор формализует ограниченный набор компоновочных правил, строит предварительные варианты и выполняет расчёты, которые должны проверяться инженером на реальных исходных данных.
С чего начинается генерация
Чтобы реализовать первоначальный вариант от пользователя прежде всего требуется задать территорию, где бы ему хотелось видеть подстанцию, задать нужные параметры, а именно необходимую ему мощность, класс напряжения высокой стороны и некоторые опциональные параметры (класс напряжения низкой стороны, процент резервной мощности, параметры Sk/Ik для сети, тип выключателя). Для фронта (визуальной части) я использовал MapLibre GL, т.к. использовал его в других проектах и для режима редактирования, где пользователь рисует полигон территории и для режима результата, где результат отображается ближе и в 3D. Единственное, что в режиме редактирования используется maplibre-gl-draw для того, чтобы пользователь мог нарисовать территорию подстанции, а в режиме результата — MapLibre fill-extrusion для рисования оборудования и deck.gl для рисования проводов с провисами. Вообще я хотел вместо оборудования использовать 3д модели из Three.js, и даже нашел несколько бесплатных моделей трансформаторов, но сразу уперся в технический момент, что не смог добиться нормального отображения этих моделей на карте из-за рендеринга и отсутствия хорошего опыта фронтенд-скилла, и, наверное, можно было решить этот момент через ИИ, но мне сильно не хотелось поддаваться сладким обещаниям вайбкодинга, т.ч. я от glTF моделей отказался и стал рисовать оборудование через простые геометрические фигуры в MapLibre. Отдельная хохма как я рисовал трансформатор через куб с гребенкой ребер. Зато быстро грузится и вообще симпатично выглядит! 😊 Но фронтенд – это не то, ради чего я начинал писать, основная идея – как правильно сгенерировать.
В начале, сдув некий накопившийся слой пыли с багажа знаний из релейки и воспоминаний о подстанциях, которые я обслуживал, я задал себе вопрос – «Что вообще считать приемлемым результатом генерации?» Понятно, что нам необходимо учитывать ограничения расположения оборудования, но просто расставив его хаотично внутри территории, мы не получим адекватный результат. Соответственно я составил некий список требований для компоновки:
1) Оборудование должно использовать реалистичные типовые габариты и номинальные параметры, чтобы сохранялся правдоподобный масштаб компоновки на карте.
2) Все оборудование, зоны, проезды должны соответствовать минимально допустимому расстоянию по ПУЭ, правилам пожарной безопасности и др.
3) Минимальный состав оборудования должен влезть на территорию (т.е. нам нет смысла если все оборудование высокой стороны влезет, а для КРУН не останется места)
4) Оборудование не должно пересекаться и должно располагаться внутри территории
5) компоновка должна соответствовать электрической схеме (т.е. выключатели и разъединители должны располагаться в логическом порядке присоединения)
6) Ориентация оборудования должна соответствовать его связям (т.е. оборудование нельзя свободно поворачивать без учёта его конструкции)
Как рождается раскладка
Бэкенд я писал на Kotlin плюс Spring Boot, а вся геометрия — на JTS/GeoTools. Опять же это то, что мне привычно с рабочих моментов. Полигон участка приходит в WGS84, первым делом проецируется в локальную метрическую систему координат (в градусах считать отступы для ПУЭ — такое себе развлечение), и дальше вся математика идёт в метрах.
Генерация устроена как конвейер, который строит подстанцию в том же порядке, в каком о ней думает проектировщик (вернее я бы так строил, если бы был им): сначала самое тяжёлое и первоочередное, потом последовательно наслаивается компонент за компонентом. На самом деле я лукавлю, потому что в реальности вероятно я бы шел от питающих высоковольтных линий, т.е. с краю, но тут таких данных нет (хотя в дальнейшем у меня есть желание прикрутить точки входа или как-то брать их из ОСМ окружения, но это потом). Поэтому тут стоит еще раз повторить об условности генератора в части моментов.
Первыми на участке генерируются силовые трансформаторы. Это основа компоновки, т.к. они самые большие, вокруг них маслоприёмники, между ними противопожарные разрывы и если трансформаторы встали неудачно, всё остальное уже не имеет смысла продолжать генерировать. Расставлять их я решил генетическим алгоритмом: хромосома кодирует позиции и углы двух трансформаторов, популяция примерно в 60 особей эволюционирует около 120 поколений, четверть лучших проходит дальше, остальные скрещиваются и мутируют за счет сдвига и поворота. Заведомо негодные варианты отбрасываются сразу: вылез за участок, трансформаторы встали не в линию или не параллельно опорной стене, разрыв между маслоприёмниками меньше нормы. По остальным копится штраф: за прижатость к границе, за отклонение от целевого расстояния между маслоприёмниками, за проблемы с противопожарным барьером
Дальше по списку: ячейки высокой стороны (выключатели, разъединители, порталы под заходы линий), ОПНы, секционный выключатель между шинами, трансформаторы напряжения, КРУН на низкой стороне, ошиновка между всем этим, кабельные каналы вторичных цепей, и в конце инфраструктура: внутренние проезды, забор с воротами, ОПУ, охранные зоны. Каждый этап знает про предыдущие и учитывает их геометрию как препятствия.
В данном моменте пришлось остановиться и переделать структуру генератора, потому что возникла одна важная проблема – не важно, как хорошо сгенерировались трансформаторы, высоковольтная часть, СВ, потому что если какую-то из частей сгенерировать не вышло, то падает вся цепочка. Потому решено было немного переделать алгоритм для трансформаторов так, чтобы отдавалась не лучшая по требованиям пара, а ленивый поток раскладок-кандидатов по убыванию качества. Таким образом, если один из этапов возвращал пустой список, мы могли бы взять следующую пару кандидатов и пробовать с ним на другой позиции, пробуя ориентировать трансформаторы относительно разных стен. Здесь же хорошо удалось внедрить разные варианты компоновки, если пользователь запросил их в количестве больше одной.
В этот момент я придумал штуку, что для наглядности пользователю было бы интересно видеть не бегущий кружок таймера, а видеть, как алгоритм расставляет варианты компоновки. Пока бэкенд перебирает раскладки, фронт периодически опрашивает трассу генерации и показывает на карте, как алгоритм работает: неудачные попытки отрисовываются красным, а что подошло зелёным. Для дела толку ноль, зато красиво, да и по времени не долго заняло реализовать.
Кабельные каналы, или как я прикручивал незначительную часть столько же, сколько делал все остальное (ну почти)
Отдельная история – это кабель-каналы вторичных цепей, по которым от оборудования к ОПУ и КРУН идут цепи защит и измерений. Намучился я с ними примерно столько же, сколько возился с ними, работая в релейке. Общая идея следующая: я выделил два этапа:
— зона рядом с высоковольтным оборудованием
— оставшаяся зона вне первой зоны
Если уже сгенерированное оборудование в целом имеет структурированную форму, то там можно, сохраняя необходимое расстояние, вести каналы вдоль оборудования, делая ответвления под кабели, подходящие к оборудованию. Для каждой из двух секций отдельный кабель-канал. А вот для внешней зоны, с одной стороны, надо не удлинять кабель-каналы, но и просто по кратчайшей провести не пойдет. В принятой модели для двух секций формируются раздельные маршруты, идущих к КРУН, кабельных каналов. Это не универсальное требование для любой подстанции, а выбранное проектное ограничение, позволяющее получить структурированную и резервированную трассировку. При этом территория подстанции – не всегда прямоугольник и при кривых территориях возникают проблемы. Здесь я использовал A* на ортогональной сетке с метровым шагом и штрафом за повороты, чтобы трассы получались прямоугольными, что в целом решило проблему, хотя я также осознаю некую условность трассировки.
От геометрии к электричеству
Досюда генератор оставался, по сути, геометрической задачей. А мне хотелось, чтобы за картинкой стояла еще и физика, т.ч. пригодился опыт из релейки. Задача была – научить генератор считать токи короткого замыкания для получившейся модели на основе реальных данных, т.е. то, что часто используется в реальной жизни. Мне такой задачей редко приходилось заниматься, т.к. уставки уже приходили готовые и рассчитанные с учетом выбранного режима, но некоторое представление о том, как это делается, у меня было.
Вкратце, из готовой раскладки собирается электрическая модель сети, схема замещения: узлы (шины ВН, шины НН посекционно) и ветви (питающая система, трансформаторы) в относительных единицах. Дальше классический вариант расчёта токов КЗ через матрицу узловых сопротивлений Zшин, которую я считаю обращением матрицы проводимостей Yшин, написав для этого небольшую, но свою комплексную матричную систему расчета. Для каждого коммутационного состояния строится приведённая матрица узловых проводимостей Ybus, после обращения которой получается матрица узловых сопротивлений Zbus. Диагональный элемент Zkk используется как эквивалентное сопротивление Тевенина относительно узла КЗ, а соответствующий столбец позволяет определить напряжения остальных узлов и вклады ветвей. В целом для такой небольшой схемы подстанции это излишне, но мы можем рассматривать разные режимы, когда какой-либо из секционных выключателей включен или отключен. Кроме того, возможно генератор расширится и вместе с ней схема подстанции, что усложнит расчет токов КЗ, поэтому подход через Ybus/Zbus и эквивалент Тевенина оказался удобной основой для дальнейшего расширения модели.
Считаются трёхфазные и двухфазные КЗ на каждой шине, ударные токи, вклады присоединений, напряжения на шинах во время КЗ. Помимо расчётов КЗ отдельно выполняется упрощённый нагрузочный расчёт с оценкой загрузки трансформаторов. Всё это в четырёх коммутационных режимах: секционные выключатели ВН и НН в разных сочетаниях включен/отключен. На фронте это реализовалось в интерактивную однолинейную схему, которая позволяет выбрать режим, увидеть токи и напряжения для участков ПС в данном режиме КЗ.
Методик расчёта при этом две — ГОСТ Р 52735-2007 «Короткие замыкания в электроустановках. Методы расчёта в электроустановках переменного тока напряжением свыше 1 кВ» и IEC 60909.
Здесь я не считал токи КЗ для других видов: однофазных, двухфазных на землю. Для этого пришлось бы добавлять нулевую последовательность, что возможно будет сделано позже. Пока нету.
Доверяй, но проверяй: пересчитываю за своим же генератором
Красивая панель с числами — это хорошо, но давайте все же пересчитаем все на бумажке. Возьму режим D со скриншота — СВ-110 отключен, СВ-10 включен. По высокой стороне секции разделены и каждая питается от своей линии, по низкой — связаны через секционник. КЗ ставлю на шине 1с-10 кВ. Панель утверждает:
Исходные данные: два трансформатора по 40 МВА (uк = 10.5%, ΔPк = 172 кВт согласно паспортным данным трансформатора), мощность КЗ системы Sк = 3800 МВА, X/R системы = 12 (выбраны как дефолтные значения системы). Считаю по ГОСТ: базисная мощность Sб = 100 МВА, напряжения средненоминальные 115/10.5 кВ, c = 1.0.
Сначала сопротивления. Sк, и uк задают модуль полного сопротивления, а не реактивную часть поэтому раскладывать на R и X нужно самому.
Система:
Трансформатор:
|Zт| = (uк/100)·(Sб/Sн) = 0.105·100/40 = 0.2625 о.е.
Rт = ΔPк·Sб/(1000·Sн²) = 172·100/(1000·40²) = 0.010750 о.е.
Xт = √(|Zт|² − Rт²) ≈ 0.262280 о.е. => Zt= 0.01075 + j0.26228
Сопротивление одной ветви — поэтому
Собираю схему замещения режима D. СВ-110 отключен — ветви не связаны по высокой стороне, каждая несёт своё сопротивление системы. СВ-10 включен — на шине 10 кВ обе ветви встают в параллель. Т.к. параметры ветвей одинаковы из-за одинаковых трансформаторов и параметров сети (ЭДС источников), то можно сказать, что Zветвь1 = Zветвь2 и соответственно Zобщ = Zветвь/2
Сходится (генератор округляет вывод до третьего знака). Ток КЗ считается по полному модулю комплексного сопротивления:
Панель показывает 38.07 в подробной таблице и 38.1.
Дальше перекрёстные проверки:
-
Вклады. Схема симметричная, поэтому неокруглённые вклады Т1 и Т2 одинаковы и в сумме дают полный ток КЗ: по 19.04 кА. Интерфейс показывает каждый как 19.03, а итог как 38.07. Сходится.
-
Напряжение на ВН во время КЗ. Ток ветви в о.е. — 3.463;
приближённо
, а панель: 0.909. При металлическом КЗ на шине 10 кВ шины 110 кВ просаживаются всего на 9%.
-
Сквозной ток по ВН. Ток НН, приведённый через отношение напряжений: 19.04·10.5/115 ≈ 1.74 кА. Панель: 1.74.
-
Ударный ток.
, постоянная времени
-
,
-
, и
против 100.6 на панели.
Итого: все шесть контрольных точек — ток, суммарные R и X, вклады, остаточное напряжение, сквозной ток, ударный ток воспроизводятся ручным расчётом с учетом округления.
Уставки — сердце релейщика
Дальше по накатанной: раз есть токи КЗ в основных режимах, можно считать уставки защит. МТЗ (ANSI 51), токовая отсечка (50), предварительная оценка базисных токов и начальных параметров для 87T, а также упрощённая оценка функции перегрузки 49, плюс проверка селективности по ступеням времени. Эти результаты не являются готовыми эксплуатационными уставками: они показывают логику предварительного выбора и требуют реальных данных ТТ и конкретного терминала защиты. Очередная условность – мы ничего не знаем про отходящие линии, какие кабели от них отходят и куда, поэтому не считаем ток КЗ у абонента и не считаем уставки на фидерах. Очередной задел на будущее.
Если для оборудования ток проверяется по максимуму, то чувствительность для защит проверяем по минимуму. Уставка токовой отсечки предварительно отстраивается от максимального тока внешнего КЗ за защищаемым трансформатором, а чувствительность проверяется по минимальному току повреждения в защищаемой зоне. Каждая уставка выводится с формулой, в которую уже подставлены числа, с подобранными трансформаторами тока (можно переключиться на вторичные величины) и указанием, где предварительный расчёт и где грубая оценка, требующая реальных данных.
IEC 61850, куда же без цифровой подстанции
Раз уж есть первичная схема и уставки, грех было не довести дело до модных нынче цифровых подстанций. Среди подстанций, где я работал, у меня только одна была цифровой, и то наполовину. Не самая моя изученная тема, т.ч. приходилось параллельно разбираться в семействе стандартов IEC 61850, его информационной модели и языке SCL. Генератор экспортирует результат в SCL-файлы стандарта IEC 61850-6: SSD как системная спецификация с моделью подстанции и требуемыми функциями, а также прототип SCD, в котором к модели подстанции добавляются IED, коммуникационная конфигурация и шаблоны типов данных. В разделе Substation выключатели и разъединители представлены элементами ConductingEquipment с типами CBR и DIS, силовые трансформаторы — элементами PowerTransformer, а функции защит связываются с логическими узлами PTOC, PIOC и PDIF. В SCD на каждую ячейку заводится контроллер присоединения и объединяющее устройство (merging unit), поднимаются GOOSE для блокировок и обменом сигналами между IED и Sampled Values для измерений, станционная и процессная шины. Модель SCL я написал руками (JAXB-классы под нужное подмножество схемы, т.к. полный сгенерированный вариант из XSD был бы переизбытком), при этом каждый выгруженный файл валидируется против официальной XSD стандарта. Каждый файл проходит XSD-валидацию для выбранной редакции схемы. Это подтверждает структурную корректность XML, но не гарантирует полную семантическую совместимость со всеми вендорскими инструментами и реальными IED: она зависит от редакции стандарта, профиля устройства и требований конкретного конфигуратора.
ИИ-ассистент
Под конец я всё-таки добавил тоже модный нынче LLM поиграться. Сначала я сделал довольно простой вариант, когда вопрос пользователя почти не модифицировался и шел модели как есть. Но почти сразу вылез момент, что пошло жуткое вранье, выдумывание формул, несуществующих констант и все это, разумеется, с серьезным видом. Ну, вы знаете, как это обычно бывает. Да, дело еще и в модели, т.к. для теста я взял бесплатный Гигачат. Посмотрел я на это безобразие и реализовал систему с карточками и контекстом. В итоге, модель перестала считать и все числа даёт движок, а ассистент только объясняет, т.е. показывает формулу, подставляет уже посчитанные значения, ссылается на пункт ПУЭ или методику. В дополнение к гигачату, добавил дипсик, который выбрал за дешевизну. С ним дело пошло бодрее.
Что в итоге
Итого получилось: Kotlin + Spring Boot + JTS на бэке и Vue + MapLibre + deck.gl на фронте, генетика для компоновки, A* для трасс, Zшин для токов КЗ, уставки из книжек РЗА, экспорт в DXF и IEC 61850 и ассистент, который объясняет, но не считает.
Но главный вывод для меня не технический. Этот генератор занял у меня полгода в свободное от работы время. Хотелось совместить свой специфический опыт из энергетики с программированием. Хотелось написать что-то, что хваленая нейронка не сможет написать. Она, конечно, может, и гораздо быстрее, но какой получится результат? Модель могла бы помочь с шаблонными классами, рефакторингом или поиском ошибки, но она не смогла бы решить, какая компоновка выглядит правдоподобно, какой коммутационный режим является расчётным, где заканчивается допустимое упрощение и почему результат противоречит реальной эксплуатации подстанции. Так что, для тех людей, кто пришел в программирование из других сфер, доменный опыт — это не балласт, который улетает в трубу при смене профессии, а преимущество, которым надо пользоваться. Почти все содержательные решения в этом проекте пришли не из программирования, а из прошлых лет на подстанциях. Код был лишь способом это оформить. Так что, если вы когда-то сменили сферу и вам жалко прошлый опыт — не жалейте, а объединяйте.
Краткий словарь
-
РЗА — релейная защита и автоматика.
-
ПС — электрическая подстанция.
-
ВН / НН — высокая и низкая стороны напряжения подстанции.
-
КЗ — короткое замыкание.
-
СВ — секционный выключатель, соединяющий две секции шин.
-
КРУН — комплектное распределительное устройство наружной установки.
-
ОПУ — общеподстанционный пункт управления.
-
ОПН — ограничитель перенапряжений.
-
ТТ — трансформатор тока.
-
ПУЭ — Правила устройства электроустановок.
-
Ybus / Zbus — матрицы узловых проводимостей и сопротивлений электрической сети.
-
SCL — язык описания конфигурации подстанции в IEC 61850; SSD описывает системные требования, SCD — сконфигурированную систему.
-
IED / MU — интеллектуальное электронное устройство и устройство слияния данных (merging unit).
-
GOOSE / SV — быстрый обмен дискретными сигналами и передача оцифрованных измерений в IEC 61850.
-
ANSI 50 / 51 / 87T / 49 — токовая отсечка, максимальная токовая защита, дифференциальная защита трансформатора и защита от тепловой перегрузки.
ссылка на оригинал статьи https://habr.com/ru/articles/1060366/