Distribution Feeder Modeling
This section contains description of distribution feeder modeling concepts and usage of the CIMantic Graphs FeederModel 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
Distribution Feeders in CIM
Full modeling of North American distribution circuits was introduced in CIM 17 to include include unbalanced medium-voltage networks, low-voltage customer-side equipment, DERs, and advanced metering infrastructure (AMI) usage points. An example of a very simple distribution feeder is shown and explained in detail below:

ConnectivityNodeused for 3-phase buses. Separate modeling of single-phase nodes not usedTerminalused to connect conducting equipment to a busACLineSegmentused for overhead lines, underground cables, and secondary triplex lines. Phasing represented usingACLineSegmentPhaseRepresentation of downstream switching devices using
Recloser,Sectionaliser, etc. PoletopLinearShuntCompensatorandRatioTapChangerdevicesEnergySourceslack bus at substationLoads can be represented at medium voltage level or broken down into individual
EnergyConsumercustomers with split-phaseTransformerTank
FeederModel Class
The FeederModel class in CIMantic Graphs provides the interface for users to access a single feeder at a time (in a manner similar to study tools such as EPRI OpenDSS or Eaton CYME). The class provides access to the typed property graph and API methods to read and write to a data source.
It can be imported using
[2]:
from cimgraph.models import FeederModel
The structure of the distribution network graphs and API methods are explained in the sections below
Loading a FeederModel from an XML File
When working with small test cases (e.g. IEEE 13 and 123 bus models), it is possible to use CIMantic Graphs without any database and instead directly build the graph from an XML file. Note: large models (e.g. IEEE 8500) will see poor performance when reading directly from the XML (approx 2 minutes to load all triples and build the full network graph).
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'] = 'cimhub_2023'
import cimgraph.data_profile.cimhub_2023 as cim
Next, use the XMLFile interface to open the XML file:
[4]:
from cimgraph.databases import XMLFile
file = XMLFile(filename='../../sample_models/ieee13.xml')
Finally, create a new FeederModel network class to load the feeder into the graph:
[5]:
network = FeederModel(container=cim.Feeder(), connection=file)
The complete network model, including both forward and reverse associations between all objects in the model has now been loaded into the FeederModel graph.
To demonstrate the structure of resulting FeederModel network, we can display a sample breaker object:
[6]:
# Get first breaker in graph
breaker = network.first(cim.Breaker)
# Display the line
Mermaid(utils.get_mermaid(breaker))
[6]:
Loading a FeederModel from a Database
When working with large models (e.g. IEEE 8500/9500 node or utility networks), it is generally advisable to load the the models into a database and then use CIM-Graph to access the feeder via its internal API.
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.
[ ]:
import os
os.environ['CIMG_CIM_PROFILE'] = 'cimhub_2023'
import cimgraph.data_profile.cimhub_2023 as cim
Next, use the interface class to your preferred database to authenticate and connect to the database.
[ ]:
from cimgraph.databases import BlazegraphConnection
os.environ['CIMG_URL'] = 'http://localhost:8889/bigdata/namespace/kb/sparql'
database = BlazegraphConnection()
Next, create a CIM Feeder object with the correct model mRID. This can be done by a) directly creating the object or b) retrieving it from the database using the .get_object() method.
[ ]:
feeder = cim.Feeder(mRID="49AD8E07-3BF9-A4E2-CB8F-C3722F837B62")
print(feeder)
[ ]:
feeder = database.get_object(mRID="49AD8E07-3BF9-A4E2-CB8F-C3722F837B62")
print(feeder)
Finally, create a new FeederModel class and pass in the feeder and database objects as the input arguments. This will authenticate with the database and load the base feeder topology into the graph
[ ]:
network = FeederModel(container=feeder, connection=database)
To ensure performance on large models, only the minimum set of Equipment, ConnectivityNode, and Terminal objects are loaded into graph with only their UUID identifiers. All attributes are left as None or [] until the object classes are populated using the .get_all_edges method.
[ ]:
# Get first breaker in graph
breaker = network.first(cim.Breaker)
# Display the breaker
Mermaid(utils.get_mermaid(breaker))
FeederModel.graph
The .graph attribute of the GraphModel dataclass provides the interface to the typed property graph with all data contained in the network model.
It is a dictionary typed first by class type (e.g. cim.ACLineSegment) and then by UUID of each element within the network model.
All objects within the graph (if added using the API) are forced to have a unique UUID identifier.
Graph Initialization
The CIM Feeder class is used to describe containment and naming of equipment and nodes within distribution feeders. For most applications, each feeder is described as having a single normal energizing substation that serves as the source for all downstream customers.
[ ]:
diagram_text = utils.get_mermaid_path(cim.Feeder, "Equipments", show_attributes=False)
diagram_text = utils.add_mermaid_path(cim.Feeder, "ConnectivityNodes", diagram_text, show_attributes=False)
diagram_text = utils.add_mermaid_path(cim.Feeder, "NormalEnergizingSubstation", diagram_text, show_attributes=False)
diagram_text = utils.add_mermaid_path(cim.Equipment, "Measurements", diagram_text, show_attributes=False)
diagram_text = utils.add_mermaid_path(cim.ConnectivityNode, "Terminals", diagram_text, show_attributes=False)
Mermaid(diagram_text)
Graph Expansion
One of the key features of CIMantic graphs is the elimination of all custom database queries to access information regarding equipment, impedances, measurements etc. Instead, a single API method is used to extract all information about the
The .get_all_edges() method is the core library method that enables the flexibility of CIM-Graph to query for CIM objects of any class and build the knowledge graph without custom queries.
The arguments of the method are
cim_class (type): The CIM class for which to retrieve edges (e.g.
cim.Breaker)
[ ]:
network.get_all_edges(cim.Breaker)
[ ]:
# Display the same breaker
Mermaid(utils.get_mermaid(breaker))