This repo contains the GridAPPS-D services for transmission and distribution topology. The core algorithms are currently being migrated to https://github.com/PNNL-CIM-Tools/CIM-Graph-Topology-Processor and rebuilt using CIMantic Graphs labeled property graphs instead of the linked list data structures used in this repo.
The original topology processor services have been moved into the archive
directory and based on the LinkNet(TM) open-source data structure for mapping CIM ConnectivityNodes and Terminals developed by IncSys Corp. LinkNet(TM) is a trademark of Incremental Systems Corporation and is used with permission.
The topology service uses a new topic and keyword. mRID
can be that of a cim:Feeder
, cim:FeederArea
, or cim:DistributionArea
.
topic = "goss.gridappsd.request.data.cimtopology"
message = {
"requestType": "GET_DISTRIBUTED_AREAS",
"mRID": "FEEDER-1234-ABCD-MRID",
"resultFormat": "JSON"
}
message = gapps.get_response(topic, message, timeout=30)
The new topology processor response will be formatted as JSON-LD, with mRID
replaced with @id
and @type
:
{
"DistributionArea": {
"@id": "uuid-string",
"@type": "DistributionArea",
"Substations": [
{
"@id": "uuid-string",
"@type": "Substation",
"NormalEnergizedFeeder": [
{
"@id": "uuid-string",
"@type": "Feeder",
"FeederArea": {
"@id": "uuid-string",
"@type": "FeederArea",
"BoundaryTerminals": [
{
"@id": "uuid-string",
"@type": "Terminal"
}
],
"AddressableEquipment": [
{
"@id": "uuid-string",
"@type": "Breaker"
},
],
"UnaddressableEquipment": [
{
"@id": "uuid-string",
"@type": "PowerTransformer"
},
{
"@id": "uuid-string",
"@type": "EnergySource"
}
],
"Measurements": [
{
"@id": "uuid-string",
"@type": "Analog"
},
{
"@id": "uuid-string",
"@type": "Discrete"
}
],
"SwitchAreas": [
{
"@id": "uuid-string",
"@type": "SwitchArea",
"FeederArea": {
"@id": "uuid-string",
"@type": "FeederArea"
},
"BoundaryTerminals": [
{
"@id": "uuid-string",
"@type": "Terminal"
}
],
"AddressableEquipment": [
{
"@id": "uuid-string",
"@type": "LinearShuntCompensator"
}
],
"UnaddressableEquipment": [
{
"@id": "uuid-string",
"@type": "ACLineSegment"
}
"Measurements": [
{
"@id": "uuid-string",
"@type": "Analog"
},
{
"@id": "uuid-string",
"@type": "Discrete"
}
],
"SecondaryAreas": [
{
"@id": "uuid-string",
"@type": "SecondaryArea",
"SwitchArea": {
"@id": "uuid-string",
"@type": "SwitchArea"
},
"BoundaryTerminals": [
{
"@id": "9d06670e-f8ad-46a1-9854-bba7adaf1cf0",
"@type": "Terminal"
}
],
"AddressableEquipment": [
{
"@id": "uuid-string",
"@type": "PowerElectronicsConnection"
}
],
"UnaddressableEquipment": [
{
"@id": "uuid-string",
"@type": "EnergyConsumer"
}
],
"Measurements": [
{
"@id": "uuid-string",
"@type": "Analog"
}
]
}
]
}
]
}
}
]
}
]
}
}
The Topology Processor service generates a series of linked lists that are used to create a spanning tree of nodes. The spanning tree is used to identify islands and substation connectivity.
The service is used in conjunction with a GridAPPS-D simulation and publishes the topology of simulated feeder in response to switching actions and other topology changes.
To subscribe to the Topology Processor Service, use the service_output_topic()
method from the GridAPPS-D Python library:
from gridappsd.topics import service_output_topic
topic = service_output_topic("gridappsd-topology-processor", simulation_id)
The Topology Processor publishes a Python dictionary of feeders and islands in the format
Message = {"feeder_id": "_49AD8E07-3BF9-A4E2-CB8F-C3722F837B62",
"timestamp": 1645840953,
"feeders": {"feeder_0": {"PowerTransformer": "_1XFMR-SUB1-MRID",
"ConnectivityNode": ["_ABCD-NODE01-MRID", "_BCDE-NODE02-MRID"]},
{"feeder_1": {"PowerTransformer": "_2XFMR-SUB2-MRID",
"ConnectivityNode": ["_CDEF-NODE35-MRID", "_DEFG-NODE36-MRID"]},
{"feeder_n": {"PowerTransformer": "_3XFMR-SUB3-MRID",
"ConnectivityNode": ["_UWXY-NODE88-MRID", "_WXYZ-Node89-MRID"]}},
"islands": {"island_0": {"SynchronousMachine": ["_1DER-DIES-MRID", "_2DER-WIND-MRID"],
"ConnectivityNode": ["_1234-NODE44-MRID", "_2345-NODE45-MRID"]}}
To subscribe to the service create a class or function definition that is then passed to the gapps.subscribe()
method.
A working example is available in the topo_service_tester.py
script, which subscribes to the topology service of a running simulation and then prints feeder and island info to the terminal window as switching actions are made.
output_topic = "/topic/goss.gridappsd.simulation.topologyprocessor."+str(viz_simulation_id)+".output"
def DemoTPsubscriber(headers, message):
# Extract time and measurement values from message
feeder_id = message["feeder_id"]
timestamp = message["timestamp"]
feeders = message["feeders"]
islands = message["islands"]
# Parse topology as needed
conn_id = gapps.subscribe(topic, DemoTPsubscriber)
The Topology Processor also includes a background service daemon, which is included in the GridAPPS-D platform as of [INSERT RELEASE INFO]
There are three API calls that can be made.
This API call generates the full topology dictionary for the feeder using the normally-open / normally-closed switch positions in the CIM XML feeder model.
topic = "goss.gridappsd.request.data.topology"
message = {
"requestType": "GET_BASE_TOPOLOGY",
"modelID": "_FEEDER-1234-ABCD-MRID",
"resultFormat": "JSON"
}
message = gapps.get_response(topic, message, timeout=30)
It returns a Python dictionary / JSON string message in the following format:
{
"feeder_id": "_49AD8E07-3BF9-A4E2-CB8F-C3722F837B62",
"feeders": {
"feeder_0": {
"PowerTransformer":"_1XFMR-SUB1-MRID",
"ConnectivityNode": ["_ABCD-NODE01-MRID", "_BCDE-NODE02-MRID"]
},
"feeder_1": {
"PowerTransformer": "_2XFMR-SUB2-MRID",
"ConnectivityNode": ["_CDEF-NODE35-MRID", "_DEFG-NODE36-MRID"]
},
"feeder_n": {
"PowerTransformer": "_3XFMR-SUB3-MRID",
"ConnectivityNode": ["_UWXY-NODE88-MRID", "_WXYZ-Node89-MRID"]}
},
"islands": {
"island_0": {
"SynchronousMachine": ["_1DER-DIES-MRID", "_2DER-WIND-MRID"],
"ConnectivityNode": ["_1234-NODE44-MRID", "_2345-NODE45-MRID"]
}
},
"connectivity": {
"_ABCD-NODE01-MRID": {
"name": "node01",
"TopologicalNode": "_TOPONODE-001D-MRID",
"nominalVoltage": "4160",
"ACLineSegment": ["_ACLINE-LINE-4136-MRID"],
"Breaker": [],
"EnergyConsumer": ["_LOAD-DD71-9858-MRID"],
"Fuse": [],
"House": [],
"LinearShuntCompensator": ["_LINEAR-CAP1-MRID"],
"LoadBreakSwitch": [],
"PowerTransformer": [],
"RatioTapChanger": [],
"Recloser": [],
"TransformerTank": [],
"SynchronousMachine": [],
"PowerElectronicsConnection": [],
"Measurement": [ "_778MEAS1-D427-MRID", "275MEAS2-F344-MRID"],
"Feeder": ["feeder_0", "feeder_2"],
"Island": [],
"node": 7,
"list": 8
},
"_1234-NODE44-MRID": {
"name": "node44",
"TopologicalNode": "_TOPONODE-044D-MRID",
"nominalVoltage": "208",
"ACLineSegment": ["_ACLINE-LINE-4378-MRID"],
"Breaker": [],
"EnergyConsumer": ["_LOAD-AA45-6980-MRID"],
"Fuse": [],
"House": ["_HOUSE-FF45-5948-MRID"],
"LinearShuntCompensator": [],
"LoadBreakSwitch": [],
"PowerTransformer": [],
"RatioTapChanger": [],
"Recloser": [],
"TransformerTank": [],
"SynchronousMachine": [],
"PowerElectronicsConnection": ["_SOLAR-JJ78-4598-MRID"],
"Measurement": [ "_576MEAS81-D985-MRID", "985MEAS92-F968-MRID"],
"Feeder": [],
"Island": ["island_0"],
"node": 98,
"list": 230
}
},
"equipment": {
"ACLineSegment": {
"_ACLINE-LINE-4136-MRID": {
"name": "632645",
"node1": "_ABCD-NODE01-MRID",
"term1": "_43A5-TERM23-MRID",
"node2": "_BCDE-NODE02-MRID",
"term2": "_537F-TERM24-MRID"
}
},
"Breaker": {
"_52DE9189-20DC-4C73-BDEE-E960FE1F9493": {
"name": "brkr1",
"node1": "_7BEDDADD-0A14-429F-8601-9EA8B892CA6E",
"term1": "_1D81C7FE-E88F-41E3-A900-476CA6476CCD",
"node2": "_94F822E0-7130-4205-8597-B47110BBEF4B",
"term2": "_2847E06B-C8ED-41E6-B515-C61C9E8EB4B4",
"open": 1
}
},
"EnergyConsumer": {
"_32F02D2B-EE6E-4D3F-8486-1B5CAEF70204": {
"name": "house",
"node1": "_0A98A62D-7642-4F03-8317-A8605CBDBA37",
"term1": "_2128BB42-3E2D-490A-A29D-05549E81F25D"
}
},
"House": {},
"Fuse": {
"_43EF8365-F932-409B-A51E-FBED3F6DFFAA": {
"term1": "_3621713B-852E-4F95-8586-2D55313ED673",
"term2": "_D1CF8D27-7793-45FD-BA55-ADDB77AFED1E",
"node1": "_C6256170-E6ED-4F91-8EBD-748090C3FDD5",
"node2": "_ADDB7A30-5A3C-4179-AF5D-5C9A7213B0E7",
"open": 1
}
},
"LinearShuntCompensator": {
"_A9DE8829-58CB-4750-B2A2-672846A89753": {
"name": "cap1",
"node1": "_63DFBEA0-CD06-4D2E-B956-DF9517BE057B",
"term1": "_5B38070B-E918-4EAA-8BDB-8B3CE4F8A917"
},
},
"LoadBreakSwitch": {
"_2858B6C2-0886-4269-884C-06FA8B887319": {
"name": "sect1",
"node1": "_8E99F99D-FE8F-420B-AC49-0B52DF5362AB",
"term1": "_8F517DFE-D985-4D24-8339-96FA2A789E88",
"node2": "_2A6DC4DD-D3DC-434D-A187-D2C58A0A72C8",
"term2": "_02AE202B-D91B-4EAD-8EC9-3B87BDD67C8B",
"open": 1
},
},
"PowerTransformer": {
"_259E820F-B4AF-4E1A-8271-687534EDAECC": {
"name": "sub3",
"node1": "_A8A25B50-3AE3-4A31-A18B-B3FA13397ED3",
"term1": "_717DFB1A-A300-444D-8D3B-0A093EAAD47B",
"node2": "_7BEDDADD-0A14-429F-8601-9EA8B892CA6E",
"term2": "_BB0411D7-5261-433D-B327-549DA536EEEC",
"bus1": "sourcebus",
"tname1": "sub3_T1",
"volt1": 115000,
"phase1": {},
"bus2": "650",
"tname2": "sub3_T2",
"volt2": 4160,
"phase2": {},
"bus3": "650z",
"term3": "_F6CE3095-9089-4B61-9C13-C7647ADBA888",
"node3": "_04984C4D-CC29-477A-9AF4-61AC7D74F16F",
"tname3": "sub3_T3",
"volt3": 13200,
"phase3": {}
},
},
"RatioTapChanger": {
"_67B57539-590B-4158-9CBB-9DBA2FE6C1F0": {
"bus1": "brkr",
"term1": "_F8856652-20FB-4760-874D-3D785E91A83E",
"node1": "_94F822E0-7130-4205-8597-B47110BBEF4B",
"tname1": "reg3_T1",
"volt1": 0,
"phase1": "C",
"bus2": "rg60",
"term2": "_F5258B9A-B51E-40DD-9A06-5918E41F3C35",
"node2": "_673E896A-DCBF-4E43-9924-BEB31C5B6005",
"tname2": "reg3_T2",
"volt2": 0,
"phase2": "C",
"TransformerTank": "_E2E0FC64-8D45-4C55-BDB9-EAB827A46FBC",
"name": "reg3",
"node": "_673E896A-DCBF-4E43-9924-BEB31C5B6005",
"term": "_F5258B9A-B51E-40DD-9A06-5918E41F3C35"
}
},
"Recloser": {
"_CE5D0651-676B-4AF3-8D67-41BF1B33E30C": {
"name": "rec1",
"node1": "_6CB5E5CE-2CD0-40CC-A979-B4F9ED05E49B",
"term1": "_EBAEF4A4-5D80-4FAD-A133-AA18607F3C31",
"node2": "_421E99BE-A834-4809-B924-84D88F634A45",
"term2": "_DD4717B2-5FCD-4E67-9BC8-DD307B80AFEA",
"open": 1
}
},
"TransformerTank": {
"_17A934C7-1510-481F-BAD7-189058957FF1": {
"bus1": "670",
"term1": "_8C674F14-D9FF-4B1C-B246-1235022CD4C2",
"node1": "_DC889FA5-7B28-4273-A1D7-205BE3E0BFED",
"tname1": "tpoletop_T1",
"volt1": 0,
"phase1": "B",
"bus2": "house",
"term2": "_8E29BA3D-9523-446F-BD9F-989D8182A723",
"node2": "_0A98A62D-7642-4F03-8317-A8605CBDBA37",
"tname2": "tpoletop_T2",
"volt2": 0,
"phase2": "s1",
"bus3": "house",
"term3": "_9D06670E-F8AD-46A1-9854-BBA7ADAF1CF0",
"node3": "_0A98A62D-7642-4F03-8317-A8605CBDBA37",
"tname3": "tpoletop_T3",
"volt3": 0,
"phase3": "s2"
},
"_B6363F07-B1BC-420B-AA4C-A34BB8F05827": {
"bus1": "brkr",
"term1": "_9AC596A8-D859-48F3-A286-D2533F9B9733",
"node1": "_94F822E0-7130-4205-8597-B47110BBEF4B",
"tname1": "reg1_T1",
"volt1": 0,
"phase1": "A",
"bus2": "rg60",
"term2": "_5A1120EE-0F2A-4698-9FF5-0F0F4F507BAF",
"node2": "_673E896A-DCBF-4E43-9924-BEB31C5B6005",
"tname2": "reg1_T2",
"volt2": 0,
"phase2": "A"
},
},
"SynchronousMachine": {},
"PowerElectronicsConnection": {
"_682AB7A9-4FBF-4204-BDE1-27EAB3425DA0": {
"name": "house",
"node1": "_0A98A62D-7642-4F03-8317-A8605CBDBA37",
"term1": "_A4B4C25C-8744-4B8B-A612-19B80AFA110D"
}
}
}
}
topic = "goss.gridappsd.request.data.topology"
message = {
"requestType": "GET_SNAPSHOT_TOPOLOGY",
"modelID": "_49AD8E07-3BF9-A4E2-CB8F-C3722F837B62",
"simulationID": "12345678",
"timestamp": "1645917817",
"resultFormat": "JSON"
}
message = gapps.get_response(topic, message, timeout=90)
This call returns the dictionary of feeder equipment used by the GridAPPS-D Distributed API.
topic = "goss.gridappsd.request.data.topology"
message = {
"requestType": "GET_SWITCH_AREAS",
"modelID": "_49AD8E07-3BF9-A4E2-CB8F-C3722F837B62",
"resultFormat": "JSON"
}
dist_api_message = gapps.get_response(topic, message, timeout=30)