电网供电管理

举报
HWCloudAI 发表于 2022/12/19 15:02:02 2022/12/19
【摘要】 电网供电管理 介绍配电网是电力系统中起重新分配电能作用的网络,直接面向电力用户。据统计,超过85%的故障停电是由于配电网故障造成的。所以需要加强配电网的管理,从而最大程度减少电网故障对用户的影响。在发生停电之前,提高供电的可靠性,当不可避免地发生停电时,需要一个有效的方式尽快恢复供电。配电网是一个天然的图数据模型----导电设备、设备容器、物理连接节点等可以作为节点,线路、连接关系可以看作...

电网供电管理

介绍

配电网是电力系统中起重新分配电能作用的网络,直接面向电力用户。据统计,超过85%的故障停电是由于配电网故障造成的。所以需要加强配电网的管理,从而最大程度减少电网故障对用户的影响。在发生停电之前,提高供电的可靠性,当不可避免地发生停电时,需要一个有效的方式尽快恢复供电。

配电网是一个天然的图数据模型----导电设备、设备容器、物理连接节点等可以作为节点,线路、连接关系可以看作边。

image.png

我们通过一个案例介绍华为图引擎GES在配电网几个典型场景上的应用。

图模型

以下是配电网的图数据模型。

image.png

下面详细列出了用到的样例数据的点类、边类及其附带的属性。

image.png

说明:此处基于电网CIM/E模型设计配电网图数据模型,通过联结节点将导电设备连接起来,导电设备包括busbarsection(母线))、energyconsumer(用户点)、fuse(熔断器)等,aclinesegment(导线段)连接的是两个不同的联结节点,resistancefreeline(无电阻导线)连接的是导电设备和联结节点,另外,导电设备包含设备类型(PSRType)、电压等级(BaseVoltage)、开关状态(status)、所属设备容器(container)等属性。

样例数据集

可点击此处下载原始数据集。

样例数据集中提供了两条线路,其中一条线路的一部分可视化展示如下:

image

创图

创图的详细流程见华为云图引擎服务 GES 实战——创图

源码

配置参数的定义。

import requests
import json
import time

class config(object):
    def __init__(self, iam_url, user_name, password, domain_name, project_name, eip, project_id, graph_name):
        self.iam_url = iam_url
        self.user_name = user_name
        self.password = password
        self.domain_name = domain_name
        self.project_name = project_name
        self.eip = eip
        self.project_id = project_id
        self.graph_name = graph_name
        self.token = self.get_token()
        
    def get_token(self):
        url = ('https://{}/v3/auth/tokens').format(self.iam_url)
        headers = {'Content-Type': 'application/json;charset=utf8'}
        body = json.dumps({"auth": { \
            "identity": { \
                "methods": ["password"], \
                "password": { \
                    "user": { \
                        "name": self.user_name, \
                        "password": self.password, \
                        "domain": { \
                            "name": self.domain_name \
                            } \
                        } \
                    } \
                }, \
            "scope": { \
                "project": { \
                    "name": self.project_name \
                    } \
                } \
            } \
            })
        r = requests.post(url=url, data=body, verify=False, headers=headers)
        return r.headers['x-subject-token']

config类的属性依次为“终端节点”、“IAM 用户名”、“IAM 用户密码”、“IAM 用户所属账户名”、“项目名称”、“公网访问地址”、“项目ID”、“token值”,其获取方式可参考调用 GES 服务业务面 API 相关参数的获取

调用API接口的定义。

class GESFunc(object):

    def __init__(self, eip, project_id, graph_name, token):
        self.eip = eip
        self.project_id = project_id
        self.graph_name = graph_name
        self.headers = {'X-Auth-Token': token, 'Content-Type': 'application/json'}

    def filter_query_vertex(self):
        url = ('http://{}/ges/v1.0/{}/graphs/{}/action?action_id=execute-gremlin-query').format(self.eip,
                                                                                                self.project_id,
                                                                                                self.graph_name)
        command = "g.V().has('container','变电站')"
        body = json.dumps({"command": command})
        r = requests.post(url=url, data=body, headers=self.headers)
        output = r.json()['data']
        return output

    def query_scope(self, id):
        url = ('http://{}/ges/v1.0/{}/graphs/{}/action?action_id=execute-algorithm').format(self.eip, self.project_id,
                                                                                            self.graph_name)
        body = json.dumps({"executionMode": "sync",
                           "algorithmName": "k_hop",
                           "parameters": {"k": 100,
                                          "source": id,
                                          "mode": "ALL"}})
        r = requests.post(url=url, data=body, headers=self.headers)
        return r.json()['data']['outputs']

    def query_consumer(self, id_list):
        url = ('http://{}/ges/v1.0/{}/graphs/{}/action?action_id=filtered-query').format(self.eip,
                                                                                         self.project_id,
                                                                                         self.graph_name)
        body = json.dumps({"executionMode": "sync",
            "filters": [
                {
                    "operator": "vertex",
                    "vertex_filter": {
                        "property_filter": {
                            "leftvalue": {
                                "label_name": "labelName"
                            },
                            "predicate": "=",
                            "rightvalue": {
                                "value": "energyconsumer"
                            }
                        }
                    }
                }
            ],
            "by": [
                {
                    "id": True,
                    "properties": True,
                    "selectedProperties": [
                        "name"
                    ]
                }
            ],
            "full_path": False,
            "vertices": id_list})
        r = requests.post(url=url, data=body, headers=self.headers)
        return r.json()['data']

    def outage_analysis(self, id):
        url = ('http://{}/ges/v1.0/{}/graphs/{}/action?action_id=path-query').format(self.eip, self.project_id,
                                                                                     self.graph_name)
        body = json.dumps(
            {
                "repeat": [
                    {
                        "operator": "bothV"
                    }
                ],
                "until": [
                    {
                        "vertex_filter": {
                            "property_filter": {
                                "leftvalue": {
                                    "property_filter": {
                                        "leftvalue": {
                                            "label_name": "labelName"
                                        },
                                        "predicate": "=",
                                        "rightvalue": {
                                            "value": "fuse"
                                        }
                                    }
                                },
                                "predicate": "&",
                                "rightvalue": {
                                    "property_filter": {
                                        "leftvalue": {
                                            "property_name": "status"
                                        },
                                        "predicate": "=",
                                        "rightvalue": {
                                            "value": "open"
                                        }
                                    }
                                }
                            }
                        }
                    }
                ],
                "queryType": "Tree",
                "emit": False,
                "times": 20,
                "by": [
                    {
                        "properties": True,
                        "selectedProperties": ["status"]
                    }
                ],
                "vertices": [
                    id
                ]
            }
        )
        r = requests.post(url=url, data=body, headers=self.headers)
        return r.json()['data']

    def query_vertex(self, id):
        url = ('http://{}/ges/v1.0/{}/graphs/{}/action?action_id=execute-gremlin-query').format(self.eip,
                                                                                                self.project_id,
                                                                                                self.graph_name)
        command = "g.V(" + id + ")"
        body = json.dumps({"command": command})
        r = requests.post(url=url, data=body, headers=self.headers)
        output = r.json()['data']
        return output

    def annular_electric_supply(self):
        url = ('http://{}/ges/v1.0/{}/graphs/{}/action?action_id=execute-algorithm').format(self.eip, self.project_id,
                                                                                            self.graph_name)
        body = json.dumps({
            "algorithmName": "circle_detection",
            "parameters": {
                "directed": False,
                "max_length": 15
            }})
        r = requests.post(url=url, data=body, headers=self.headers)
        return r.json()['jobId']

    def get_job(self, job_id):
        url = ('http://{}/ges/v1.0/{}/graphs/{}/jobs/{}/status').format(self.eip, self.project_id, self.graph_name,
                                                                        job_id)
        r = requests.get(url=url, headers=self.headers)
        output = r.json()['data']['outputs']
        return output

    def query_interconnection_switch(self, id_list):
        url = ('http://{}/ges/v1.0/{}/graphs/{}/action?action_id=filtered-query').format(self.eip, self.project_id,
                                                                                         self.graph_name)
        body = json.dumps({
            "executionMode": "sync",
            "filters": [
                {
                    "operator": "vertex",
                    "vertex_filter": {
                        "property_filter": {
                            "leftvalue": {
                                "property_name": "name"
                            },
                            "predicate": "SUBSTRING",
                            "rightvalue": {
                                "value": "联络开关"
                            }
                        }
                    }
                }
            ],
            "by": [
                {
                    "id": True,
                    "properties": True,
                    "selectedProperties": [
                        "name"
                    ]
                }
            ],
            "full_path": False,
            "vertices": id_list})
        r = requests.post(url=url, data=body, headers=self.headers)
        return r.json()['data']

创建好图之后,就可以对其进行查询和分析了。

# 需填入参数
config = config(" ", " ", " ", " ", " ", " ", " ", " ")
test = GESFunc(config.eip, config.project_id, config.graph_name, config.token)

场景演示

供电范围查询

  • 指查询指定设备所承担供电范围内的其他设备,这个需要查询的设备可以是站内变压器,也可以是变电站。
  • 这有助于设备管理,也能够清楚地知道由于变电站的故障所造成的停电范围,早作防范。
  • 一般更关心的是变电站供电的用户。

image

以上图例中,如果断开间隔开关1,其下游所有的用户都会处于停电状态。

下面是一个具体的操作示例。首先查找位于变电站中的母线。(母线是各级电压配电装置的中间环节,它的作用是汇集、分配和传送电能。)

result = test.filter_query_vertex()
print('the busbarsections in substations:')
print(result)
the busbarsections in substations:

{'vertices': [{'id': '60', 'label': 'busbarsection', 'properties': {'container': ['变电站'], 'BaseVoltage': ['交流10kV'], 'name': ['10kV Ⅰ段母线'], 'PSRType': ['站内-母线']}}, {'id': '1157', 'label': 'busbarsection', 'properties': {'container': ['变电站'], 'BaseVoltage': ['交流10kV'], 'name': ['10kVⅡ母'], 'PSRType': ['站内-母线']}}], 'runtime': 0.03743901299999999}

从结果看,我们得到了两条母线,选取其中一条母线,查看其供电范围

result = test.query_scope("1157")
print('the equipments in the scope of supply of "1157":')
print(result)
the equipments in the scope of supply of "1157":

{'data_return_size': 363, 'vertices': ['1215', '1016', '1250', '1251', '1274', '1062', '1081', '1115', '1249', '1117', '1116', '1046', '1275', '1237', '1078', '1090', '1054', '1203', '1061', '1049', '1121', '1288', '1204', '1035', '1202', '1311', '1036', '1312', '1037', '1038', '1039', '1040', '1156', '1015', '1310', '1205', '1206', '1207', '1208', '1234', '1297', '1050', '1051', '1052', '1053', '1309', '1132', '1248', '1247', '1235', '1236', '1259', '1292', '1270', '1241', '1303', '1264', '1079', '1080', '1082', '1105', '1126', '1122', '1123', '1164', '1286', '1300', '1317', '1074', '1083', '1106', '1152', '1011', '1334', '1158', '1162', '1299', '1282', '1318', '1323', '1059', '1231', '1135', '1181', '1253', '1304', '1322', '1324', '1331', '1280', '1055', '1125', '1175', '1356', '1238', '1301', '1296', '1283', '1271', '1088', '1044', '1333', '1350', '1263', '1268', '1267', '1294', '1065', '1089', '1004', '1131', '1137', '1163', '1184', '1252', '1227', '1239', '1257', '1298', '1085', '1091', '1097', '1213', '1128', '1130', '1133', '1339', '1359', '1258', '1260', '1262', '1305', '1320', '1032', '1066', '1073', '1084', '1092', '1098', '1103', '1144', '1005', '1006', '1336', '1134', '1187', '1242', '1261', '1244', '1285', '1308', '1197', '1104', '1107', '1112', '1289', '1214', '1136', '1182', '1362', '1047', '1243', '1306', '1272', '1026', '1027', '1028', '1029', '1030', '1031', '1075', '1077', '1108', '1109', '1111', '1057', '1145', '1151', '1153', '1012', '1014', '1338', '1169', '1170', '1357', '1233', '1307', '1266', '1229', '1226', '1230', '1225', '1228', '1200', '1076', '1110', '1278', '1154', '1232', '1013', '1344', '1345', '1165', '1186', '1245', '1287', '1295', '1361', '1198', '1034', '1072', '1086', '1042', '1155', '1176', '1179', '1118', '1119', '1120', '1160', '1255', '1246', '1273', '1319', '1329', '1033', '1201', '1063', '1087', '1113', '1060', '1001', '1129', '1351', '1354', '1218', '1265', '1321', '1293', '1199', '1064', '1093', '1114', '1281', '1210', '1003', '1337', '1178', '1166', '1284', '1302', '1067', '1094', '1045', '1058', '1142', '1211', '1146', '1000', '1007', '1127', '1139', '1177', '1353', '1159', '1185', '1256', '1279', '1056', '1143', '1209', '1002', '1290', '1335', '1138', '1341', '1352', '1360', '1221', '1101', '1276', '1043', '1212', '1340', '1140', '1167', '1183', '1254', '1018', '1070', '1102', '1041', '1216', '1342', '1168', '1358', '1188', '1193', '1277', '1190', '1095', '1343', '1171', '1363', '1313', '1020', '1022', '1023', '1071', '1096', '1048', '1148', '1009', '1346', '1240', '1314', '1191', '1220', '1194', '1224', '1217', '1330', '1019', '1024', '1069', '1099', '1149', '1150', '1008', '1010', '1173', '1325', '1192', '1021', '1195', '1196', '1068', '1100', '1291', '1348', '1326', '1189', '1025', '1141', '1327', '1223', '1222', '1017', '1147', '1219', '1174', '1349', '1172', '1347', '1328', '1315', '1269', '1316', '1124', '1332', '1161', '1180', '1355'], 'runtime': 0.006912, 'k': 100, 'source': '1157', 'k_hop_neighbors': 363, 'data_offset': 0, 'data_total_size': 363}

得到的结果包含供电范围内所有设备的ID。
我们比较关心的是供电范围内涉及的用户

id_list = result["vertices"]
result = test.query_consumer(id_list)
print('the consumers in the scope of supply of "1157":')
print(result)
the consumers in the scope of supply of "1157":

{'vertices': [{'id': '1164', 'properties': {'name': ['余杭国土资源局']}}, {'id': '1158', 'properties': {'name': ['杭州建设工程有限公司']}}, {'id': '1162', 'properties': {'name': ['余杭建设规划局']}}, {'id': '1163', 'properties': {'name': ['开发管理委员会']}}, {'id': '1165', 'properties': {'name': ['工程局']}}, {'id': '1160', 'properties': {'name': ['余杭投资开发有限公司']}}, {'id': '1166', 'properties': {'name': ['余杭商贸大厦']}}, {'id': '1159', 'properties': {'name': ['余杭房地产开发有限公司']}}, {'id': '1161', 'properties': {'name': ['余杭路灯管理处']}}]}

另外,如果该供电范围内有重点用户,就需要检查、调整供配电方案,例如对重点用户提供市电和发电机供电切换供电方案。

停电故障分析

关于停电,如果是非计划停电,我们需要知道的是故障出在哪里,尽快去修复。GES无论是在故障定位还是抢修路径设计方面都能发挥作用。

image

图例中,当标红用户点出现停电时,可以回溯供电路径,查找故障原因。

下面是一个具体的操作示例。本场景中我们假设由于设备故障造成某用户节点(节点ID为74)停电,我们要做的是通过路径回溯定位到故障点(假设故障原因为设备故障而非线路故障)。

result = test.outage_analysis("74")
print('the cause of the problem:')
print(result)
the cause of the problem:

{'tree': {'74(null)': {'272(null)': {'57(close)': {'243(null)': {'242(null)': {'241(null)': {'240(null)': {'239(null)': {'238(null)': {'237(null)': {'55(open)': {}}}}}}}}}}}}}

进一步查询id为55的节点详情

result = test.query_vertex("55")
print('the details of faulty equipment:')
print(result)
the details of faulty equipment:

{'vertices': [{'id': '55', 'label': 'fuse', 'properties': {'container': ['1号线'], 'BaseVoltage': ['交流10kV'], 'name': ['梨村支线03跌落式熔断器'], 'PSRType': ['柱上-跌落式熔断器'], 'status': ['open']}}], 'runtime': 0.020651665}

查询到的结果显示是因为节点ID为55的熔断器发生熔断导致的节点ID为74的用户接入点出现停电现象

环形供电查询

  • 环形供电是指电源和负荷点通过线路联结成环形的供电方式。
  • 环形供电能提高供电的可靠性,当环内任一段线路出现故障时,通过开关的切换能保证负荷点的正常供电。

image

图例中四条单路进线两两相连形成环形供电网络,当本段进线出现供电中断后,能从其他进线侧获取电能。

下面是一个具体的操作示例。本场景演示了利用GES搜索配电网中的环形供电线路

result = test.annular_electric_supply()
job_id = result
time.sleep(1)
result = test.get_job(job_id)
print('the id list of annular_electric_supply:')
print(result)
the id list of annular_electric_supply:

{'data_return_size': 1, 'min_length': 3, 'runtime': 0.0019060000000000001, 'circles': [['1250', '1251', '1249', '1054', '1203', '1035', '1202', '1036', '1204', '1049', '1237', '1046', '1274', '1250']], 'data_offset': 0, 'n': 100, 'data_total_size': 1, 'max_length': 15}

可以进一步确定环形供电路径中联络开关的位置,联络开关的常规状态是open,只有在需要的时候才会close。(为了能尽可能的减少停电的影响,我们通过将两条配电线路通过开关连接起来,以便能实现负荷之间的转供,这个用来连接两条配电线路的开关就叫“联络开关”。)

for i in range(len(result['circles'])):
    id_list = result['circles'][i]
    res = test.query_interconnection_switch(id_list)
    print('interconnection switch:')
    print(res)
interconnection switch:

{'vertices': [{'id': '1046', 'properties': {'name': ['南线小渔村委会支-临湖线联络开关']}}]}

基于查询到的结果,我们可以知道环形路径上任何设备或线路出现故障都不会影响整体的供电情况,只需要切换联络开关即可,而我们也已经知道了联络开关的位置

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。