Node Breaker Models

This section contains description of transmission node-breaker modeling concepts and usage of the CIMantic Graphs NodeBreakerModel class for accessing CIM feeder models in a centralized and distributed manner.

All diagrams within this page have been auto-generated using mermaid.js and the cimgraph.utils module of CIMantic Graphs, which can be imported using

[1]:
from cimgraph import utils
from mermaid import Mermaid

Transmission Network Models in CIM

CIM was originally designed to support full node-breaker modeling of transmission network models and substations

[2]:
# TODO: Provide sample Node Breaker Model diagram

Loading a FeederModel from an XML File

It is possible to use CIMantic Graphs without any database and instead directly build the graph from an XML file.

The first step is to import the correct CIM profile to use and set the associated environment variable used by CIM-Graph. For an explanation of CIM profiles, see Profiles Overview

[3]:
import os
os.environ['CIMG_CIM_PROFILE'] = 'cim17v40' # import and env var must match

import cimgraph.data_profile.cim17v40 as cim # import and env var must match

Next, use the XMLFile interface to open the XML file:

[4]:
from cimgraph.databases import XMLFile

file = XMLFile(filename='../../sample_models/maple10nodebreaker.xml')

If custom extensions are used, provide a namespaces dictionary mapping the prefix to the custom namespaces:

[5]:
namespaces={'cim': 'http://iec.ch/TC57/CIM100#',
            'gmdm': 'http://epri.com/gmdm/2025#',
            'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
            'gad': 'http://gridappsd.org/CIM/extension#'}

file = XMLFile(filename='../../sample_models/maple10nodebreaker.xml',
               namespaces=namespaces)

Finally, create a new NodeBreakerModel network class to load the transmission model into the graph:

[6]:
from cimgraph.models import NodeBreakerModel

network = NodeBreakerModel(container=None, connection=file)
[7]:
# Get first breaker in graph
breaker = network.first(cim.Breaker)
# Display the line
Mermaid(utils.get_mermaid(breaker))
[7]:

Modifying Files

Objects can be created, modified, or deleted using the .add_to_graph(object), .delete(object), and .create('incremental_file.xml') methods

[8]:
new_breaker = cim.Breaker(name='new_breaker', open=False)
network.add_to_graph(new_breaker)
[9]:
network.delete(new_breaker)
[10]:
network.modify(breaker, 'open', True, incremental_file='breaker_incremental.xml')

Saving to a File

Use the utils.write_xml() and utils.write_json_ld methods to save modified network to file

[11]:
from cimgraph import utils

utils.write_xml(network, '../../sample_models/maple10nodebreaker_modified.xml')
utils.write_json_ld(network, '../../sample_models/maple10nodebreaker_modified.jsonld')
[ ]:

[ ]:


Advanced Concepts - Distributed Modeling

These features are still in development and intended to provide a preview of planned capabilities. Under certain use cases, users may wish to instantiate a new typed property graph for each substation and voltage level as its own standalone network.

[12]:
network = NodeBreakerModel(container=None, connection=file, distributed = True)
[13]:
for sr_area in network.distributed_areas[cim.SubGeographicalRegion].values():
    print("subregion", sr_area.container.name)
    for sub_area in sr_area.distributed_areas[cim.Substation].values():
        print("substation", sub_area.container.name)

        for vl_area in sub_area.distributed_areas[cim.VoltageLevel].values():
            print("voltage level", vl_area.container.name)

        for feeder_area in sub_area.distributed_areas[cim.Feeder].values():
            print("feeder", feeder_area.container.name, "contains PV aggregates")
            feeder_area.get_all_edges(cim.PowerElectronicsConnection)
            feeder_area.get_all_edges(cim.PhotoVoltaicUnit)
            if cim.PowerElectronicsConnection in feeder_area.graph:
                for pv in feeder_area.graph[cim.PowerElectronicsConnection].values():
                    print(pv.name, float(pv.p)/1000000, "MW")
            else:
                print("none")

[ ]: