cim-tables 0.1.0a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cim_tables-0.1.0a1/.gitignore +222 -0
- cim_tables-0.1.0a1/DISCLAIMER.md +24 -0
- cim_tables-0.1.0a1/LICENSE +28 -0
- cim_tables-0.1.0a1/PKG-INFO +243 -0
- cim_tables-0.1.0a1/README.md +213 -0
- cim_tables-0.1.0a1/cimtables/__init__.py +115 -0
- cim_tables-0.1.0a1/cimtables/binder.py +191 -0
- cim_tables-0.1.0a1/cimtables/connectivity.py +285 -0
- cim_tables-0.1.0a1/cimtables/diff.py +64 -0
- cim_tables-0.1.0a1/cimtables/document.py +191 -0
- cim_tables-0.1.0a1/cimtables/grammar.lark +69 -0
- cim_tables-0.1.0a1/cimtables/graph_write.py +320 -0
- cim_tables-0.1.0a1/cimtables/impedance.py +80 -0
- cim_tables-0.1.0a1/cimtables/parser.py +252 -0
- cim_tables-0.1.0a1/cimtables/py.typed +0 -0
- cim_tables-0.1.0a1/cimtables/records.py +29 -0
- cim_tables-0.1.0a1/cimtables/synthetic.py +22 -0
- cim_tables-0.1.0a1/cimtables/units.py +25 -0
- cim_tables-0.1.0a1/cimtables/validate.py +294 -0
- cim_tables-0.1.0a1/cimtables/writer.py +498 -0
- cim_tables-0.1.0a1/docs/CIMTBL_DESIGN.md +466 -0
- cim_tables-0.1.0a1/pyproject.toml +68 -0
- cim_tables-0.1.0a1/tests/fixtures/ieee13.cimtbl +146 -0
- cim_tables-0.1.0a1/tests/fixtures/ieee14.cimtbl +19 -0
- cim_tables-0.1.0a1/tests/fixtures/wire_infos.cimtbl +6 -0
- cim_tables-0.1.0a1/tests/test_bind_cim18v17.py +226 -0
- cim_tables-0.1.0a1/tests/test_binder.py +264 -0
- cim_tables-0.1.0a1/tests/test_connectivity.py +339 -0
- cim_tables-0.1.0a1/tests/test_diff.py +79 -0
- cim_tables-0.1.0a1/tests/test_document.py +212 -0
- cim_tables-0.1.0a1/tests/test_get_qty.py +163 -0
- cim_tables-0.1.0a1/tests/test_graph_write.py +198 -0
- cim_tables-0.1.0a1/tests/test_impedance.py +95 -0
- cim_tables-0.1.0a1/tests/test_load_model.py +175 -0
- cim_tables-0.1.0a1/tests/test_parser.py +446 -0
- cim_tables-0.1.0a1/tests/test_units.py +42 -0
- cim_tables-0.1.0a1/tests/test_update.py +141 -0
- cim_tables-0.1.0a1/tests/test_validate.py +130 -0
- cim_tables-0.1.0a1/tests/test_writer.py +195 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
.vscode/*
|
|
2
|
+
|
|
3
|
+
# Byte-compiled / optimized / DLL files
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[codz]
|
|
6
|
+
*$py.class
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
build/
|
|
14
|
+
develop-eggs/
|
|
15
|
+
dist/
|
|
16
|
+
downloads/
|
|
17
|
+
eggs/
|
|
18
|
+
.eggs/
|
|
19
|
+
lib/
|
|
20
|
+
lib64/
|
|
21
|
+
parts/
|
|
22
|
+
sdist/
|
|
23
|
+
var/
|
|
24
|
+
wheels/
|
|
25
|
+
share/python-wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
MANIFEST
|
|
30
|
+
|
|
31
|
+
# PyInstaller
|
|
32
|
+
# Usually these files are written by a python script from a template
|
|
33
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
34
|
+
*.manifest
|
|
35
|
+
*.spec
|
|
36
|
+
|
|
37
|
+
# Installer logs
|
|
38
|
+
pip-log.txt
|
|
39
|
+
pip-delete-this-directory.txt
|
|
40
|
+
|
|
41
|
+
# Unit test / coverage reports
|
|
42
|
+
htmlcov/
|
|
43
|
+
.tox/
|
|
44
|
+
.nox/
|
|
45
|
+
.coverage
|
|
46
|
+
.coverage.*
|
|
47
|
+
.cache
|
|
48
|
+
nosetests.xml
|
|
49
|
+
coverage.xml
|
|
50
|
+
*.cover
|
|
51
|
+
*.py.cover
|
|
52
|
+
*.lcov
|
|
53
|
+
.hypothesis/
|
|
54
|
+
.pytest_cache/
|
|
55
|
+
cover/
|
|
56
|
+
|
|
57
|
+
# Translations
|
|
58
|
+
*.mo
|
|
59
|
+
*.pot
|
|
60
|
+
|
|
61
|
+
# Django stuff:
|
|
62
|
+
*.log
|
|
63
|
+
local_settings.py
|
|
64
|
+
db.sqlite3
|
|
65
|
+
db.sqlite3-journal
|
|
66
|
+
|
|
67
|
+
# Flask stuff:
|
|
68
|
+
instance/
|
|
69
|
+
.webassets-cache
|
|
70
|
+
|
|
71
|
+
# Scrapy stuff:
|
|
72
|
+
.scrapy
|
|
73
|
+
|
|
74
|
+
# Sphinx documentation
|
|
75
|
+
docs/_build/
|
|
76
|
+
|
|
77
|
+
# PyBuilder
|
|
78
|
+
.pybuilder/
|
|
79
|
+
target/
|
|
80
|
+
|
|
81
|
+
# Jupyter Notebook
|
|
82
|
+
.ipynb_checkpoints
|
|
83
|
+
|
|
84
|
+
# IPython
|
|
85
|
+
profile_default/
|
|
86
|
+
ipython_config.py
|
|
87
|
+
|
|
88
|
+
# pyenv
|
|
89
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
90
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
91
|
+
# .python-version
|
|
92
|
+
|
|
93
|
+
# pipenv
|
|
94
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
95
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
96
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
97
|
+
# install all needed dependencies.
|
|
98
|
+
# Pipfile.lock
|
|
99
|
+
|
|
100
|
+
# uv
|
|
101
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
102
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
103
|
+
# commonly ignored for libraries.
|
|
104
|
+
# uv.lock
|
|
105
|
+
|
|
106
|
+
# poetry
|
|
107
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
108
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
109
|
+
# commonly ignored for libraries.
|
|
110
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
111
|
+
# poetry.lock
|
|
112
|
+
# poetry.toml
|
|
113
|
+
|
|
114
|
+
# pdm
|
|
115
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
116
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
117
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
118
|
+
# pdm.lock
|
|
119
|
+
# pdm.toml
|
|
120
|
+
.pdm-python
|
|
121
|
+
.pdm-build/
|
|
122
|
+
|
|
123
|
+
# pixi
|
|
124
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
125
|
+
# pixi.lock
|
|
126
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
127
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
128
|
+
.pixi/*
|
|
129
|
+
!.pixi/config.toml
|
|
130
|
+
|
|
131
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
132
|
+
__pypackages__/
|
|
133
|
+
|
|
134
|
+
# Celery stuff
|
|
135
|
+
celerybeat-schedule*
|
|
136
|
+
celerybeat.pid
|
|
137
|
+
|
|
138
|
+
# Redis
|
|
139
|
+
*.rdb
|
|
140
|
+
*.aof
|
|
141
|
+
*.pid
|
|
142
|
+
|
|
143
|
+
# RabbitMQ
|
|
144
|
+
mnesia/
|
|
145
|
+
rabbitmq/
|
|
146
|
+
rabbitmq-data/
|
|
147
|
+
|
|
148
|
+
# ActiveMQ
|
|
149
|
+
activemq-data/
|
|
150
|
+
|
|
151
|
+
# SageMath parsed files
|
|
152
|
+
*.sage.py
|
|
153
|
+
|
|
154
|
+
# Environments
|
|
155
|
+
.env
|
|
156
|
+
.envrc
|
|
157
|
+
.venv
|
|
158
|
+
env/
|
|
159
|
+
venv/
|
|
160
|
+
ENV/
|
|
161
|
+
env.bak/
|
|
162
|
+
venv.bak/
|
|
163
|
+
|
|
164
|
+
# Spyder project settings
|
|
165
|
+
.spyderproject
|
|
166
|
+
.spyproject
|
|
167
|
+
|
|
168
|
+
# Rope project settings
|
|
169
|
+
.ropeproject
|
|
170
|
+
|
|
171
|
+
# mkdocs/Zensical documentation
|
|
172
|
+
/site
|
|
173
|
+
|
|
174
|
+
# mypy
|
|
175
|
+
.mypy_cache/
|
|
176
|
+
.dmypy.json
|
|
177
|
+
dmypy.json
|
|
178
|
+
|
|
179
|
+
# Pyre type checker
|
|
180
|
+
.pyre/
|
|
181
|
+
|
|
182
|
+
# pytype static type analyzer
|
|
183
|
+
.pytype/
|
|
184
|
+
|
|
185
|
+
# Cython debug symbols
|
|
186
|
+
cython_debug/
|
|
187
|
+
|
|
188
|
+
# PyCharm
|
|
189
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
190
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
191
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
192
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
193
|
+
# .idea/
|
|
194
|
+
|
|
195
|
+
# Abstra
|
|
196
|
+
# Abstra is an AI-powered process automation framework.
|
|
197
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
198
|
+
# Learn more at https://abstra.io/docs
|
|
199
|
+
.abstra/
|
|
200
|
+
|
|
201
|
+
# Visual Studio Code
|
|
202
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
|
|
203
|
+
# can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
204
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer, you
|
|
205
|
+
# could uncomment the following to ignore the entire vscode folder
|
|
206
|
+
# .vscode/
|
|
207
|
+
# Temporary file for partial code execution
|
|
208
|
+
tempCodeRunnerFile.py
|
|
209
|
+
|
|
210
|
+
# Ruff stuff:
|
|
211
|
+
.ruff_cache/
|
|
212
|
+
|
|
213
|
+
# PyPI configuration file
|
|
214
|
+
.pypirc
|
|
215
|
+
|
|
216
|
+
# Marimo
|
|
217
|
+
marimo/_static/
|
|
218
|
+
marimo/_lsp/
|
|
219
|
+
__marimo__/
|
|
220
|
+
|
|
221
|
+
# Streamlit
|
|
222
|
+
.streamlit/secrets.toml
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Disclaimer
|
|
2
|
+
|
|
3
|
+
This material was prepared as an account of work sponsored by an agency of the United States Government. Neither the
|
|
4
|
+
United States Government nor the United States Department of Energy, nor Battelle, nor any of their employees, nor any
|
|
5
|
+
jurisdiction or organization that has cooperated in the development of these materials, makes any warranty, express or
|
|
6
|
+
implied, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness or any
|
|
7
|
+
information, apparatus, product, software, or process disclosed, or represents that its use would not infringe
|
|
8
|
+
privately owned rights.
|
|
9
|
+
|
|
10
|
+
Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or
|
|
11
|
+
otherwise does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States
|
|
12
|
+
Government or any agency thereof, or Battelle Memorial Institute. The views and opinions of authors expressed herein do
|
|
13
|
+
not necessarily state or reflect those of the United States Government or any agency thereof.
|
|
14
|
+
|
|
15
|
+
<div align="center">
|
|
16
|
+
|
|
17
|
+
PACIFIC NORTHWEST NATIONAL LABORATORY<br>
|
|
18
|
+
operated by<br>
|
|
19
|
+
BATTELLE<br>
|
|
20
|
+
for the<br>
|
|
21
|
+
UNITED STATES DEPARTMENT OF ENERGY<br>
|
|
22
|
+
under Contract DE-AC05-76RL01830
|
|
23
|
+
|
|
24
|
+
</div>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Battelle Memorial Institute; All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: cim-tables
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: The .cimtbl DSL: parser, profile-reflective validator, and graph-write/binder core for cim-graph
|
|
5
|
+
Project-URL: Homepage, https://github.com/PNNL-CIM-Tools/CIM-Tables
|
|
6
|
+
Project-URL: Documentation, https://github.com/PNNL-CIM-Tools/CIM-Tables/blob/main/docs/CIMTBL_DESIGN.md
|
|
7
|
+
Project-URL: Repository, https://github.com/PNNL-CIM-Tools/CIM-Tables
|
|
8
|
+
Project-URL: Issues, https://github.com/PNNL-CIM-Tools/CIM-Tables/issues
|
|
9
|
+
Project-URL: Models, https://github.com/PNNL-CIM-Tools/CIMTBL-Models
|
|
10
|
+
Author-email: "A. Anderson" <19935503+AAndersn@users.noreply.github.com>
|
|
11
|
+
License-Expression: BSD-3-Clause
|
|
12
|
+
License-File: DISCLAIMER.md
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Keywords: cim,cim-graph,dsl,grid-models,power-systems
|
|
15
|
+
Classifier: Development Status :: 3 - Alpha
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Science/Research
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Requires-Dist: cim-graph<0.7,>=0.6.0a2
|
|
27
|
+
Requires-Dist: cim-profiles<0.2,>=0.1.0a1
|
|
28
|
+
Requires-Dist: lark>=1.1.9
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# CIM-Tables
|
|
32
|
+
|
|
33
|
+
**A CIM input file you can write in Notepad.**
|
|
34
|
+
|
|
35
|
+
`cimtables` reads `.cimtbl`, a plain-text table format for building power-system models in the IEC Common
|
|
36
|
+
Information Model (CIM), and turns it into live [cim-graph](https://github.com/PNNL-CIM-Tools/CIM-Graph)
|
|
37
|
+
objects that can be saved as standard CIM RDF/XML or JSON-LD.
|
|
38
|
+
|
|
39
|
+
## Why this exists
|
|
40
|
+
|
|
41
|
+
CIM is the industry's common language for describing a power grid, but it has never had a format people can
|
|
42
|
+
*write*. Its exchange formats, RDF/XML and JSON-LD, are produced and consumed by software: every object is a
|
|
43
|
+
block of namespaced XML, every link between objects is a UUID, and adding one load to a feeder means hand-editing
|
|
44
|
+
dozens of lines whose meaning is spread across the file. Nobody opens a CIM XML file in a text editor to build a
|
|
45
|
+
model.
|
|
46
|
+
|
|
47
|
+
So in practice, CIM models are built some other way. A model is drawn in a vendor tool, or written in a
|
|
48
|
+
simulator's native format (an OpenDSS `.dss` file, a PSS/E `.raw` file) and then run through a converter. Each
|
|
49
|
+
converter carries its own mapping from the native format's ideas to CIM's, and the CIM model you end up with is
|
|
50
|
+
only as faithful as that mapping. When something is wrong, you debug the converter, not the model.
|
|
51
|
+
|
|
52
|
+
`.cimtbl` removes the middle step. It is to CIM what a `.dss` file is to OpenDSS, except that its vocabulary
|
|
53
|
+
**is** CIM:
|
|
54
|
+
|
|
55
|
+
- every table is a CIM class (`Table ACLineSegment:`),
|
|
56
|
+
- every column header is a CIM attribute or association name (`length`, `BaseVoltage`, `PerLengthImpedance`),
|
|
57
|
+
- every row is one CIM object,
|
|
58
|
+
- units are written once, on the column header (`length (ft)`, `p (kW)`, `r0 (pu)`), and converted for you.
|
|
59
|
+
|
|
60
|
+
There is no mapping to maintain because there is nothing to map. If the CIM profile has a class or attribute,
|
|
61
|
+
you can write it; if it doesn't, you get an error pointing at the line. The result is a file you can create in
|
|
62
|
+
Notepad, read top to bottom, review in a pull request, diff in git, and ask an LLM to edit.
|
|
63
|
+
|
|
64
|
+
## What it looks like
|
|
65
|
+
|
|
66
|
+
A small radial feeder: one source, two line segments and two loads.
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
# tiny_feeder.cimtbl
|
|
70
|
+
|
|
71
|
+
Profile = cim18v17
|
|
72
|
+
Authority = https://example.com/models
|
|
73
|
+
Model = tiny_feeder
|
|
74
|
+
|
|
75
|
+
Object BasePower: mRID=sbase, basePower (MVA)=100
|
|
76
|
+
Object Substation: mRID=sub
|
|
77
|
+
Object Feeder: mRID=fdr, NormalEnergizingSubstation=sub
|
|
78
|
+
|
|
79
|
+
Table BaseVoltage: mRID, nominalVoltage (kV)
|
|
80
|
+
bv_12kv, 12.47
|
|
81
|
+
|
|
82
|
+
Object EnergySource: mRID=source, node=sourcebus, phases=ABC, nominalVoltage (kV)=12.47, BaseVoltage=bv_12kv, EquipmentContainer=fdr
|
|
83
|
+
|
|
84
|
+
Table ACLineSegment: mRID, node1, node2, phases, length (ft), r (ohm), x (ohm), BaseVoltage, EquipmentContainer=fdr
|
|
85
|
+
ln_trunk, sourcebus, n1, ABC, 2000, 0.38, 0.75, bv_12kv
|
|
86
|
+
ln_branch, n1, n2, C, 500, 0.12, 0.20, bv_12kv
|
|
87
|
+
|
|
88
|
+
Table EnergyConsumer: mRID, node, phases, p (kW), q (kVAr), BaseVoltage, EquipmentContainer=fdr
|
|
89
|
+
ld_n1, n1, ABC, 1155, 660, bv_12kv
|
|
90
|
+
ld_n2, n2, C, 170, 80, bv_12kv
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Load it, and save it as CIM:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import cimtables
|
|
97
|
+
from cimgraph.utils import write_xml
|
|
98
|
+
|
|
99
|
+
network = cimtables.load_model('tiny_feeder.cimtbl') # a cim-graph FeederModel for Feeder `fdr`
|
|
100
|
+
write_xml(network, 'tiny_feeder.xml') # standard CIM RDF/XML
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
That is the whole model. Besides the objects you wrote, the loader made what CIM requires
|
|
104
|
+
but no person wants to type: two `Terminal`s per line (`ln_trunk_T1`, `ln_trunk_T2`), one per load and source,
|
|
105
|
+
the `ConnectivityNode`s they meet at (`sourcebus`, `n1`, `n2`), the per-phase children (`ln_trunk_A`,
|
|
106
|
+
`ln_trunk_B`, `ln_trunk_C`, `ln_branch_C`) and each Terminal's `PhaseCode`. The line lengths are stored as
|
|
107
|
+
609.6 m and 152.4 m, and the loads as 1,155,000 W, because CIM holds SI units; you wrote feet and kilowatts.
|
|
108
|
+
|
|
109
|
+
Larger examples, including the IEEE 13-bus feeder and transmission test cases, are in
|
|
110
|
+
[CIMTBL-Models](https://github.com/PNNL-CIM-Tools/CIMTBL-Models).
|
|
111
|
+
|
|
112
|
+
## How it stays true to CIM
|
|
113
|
+
|
|
114
|
+
`.cimtbl` is a different *spelling* of a CIM model, not a different model. The rules that keep it that way:
|
|
115
|
+
|
|
116
|
+
- **The profile is the schema.** `cimtables` has no list of supported classes. It reads the CIM profile itself
|
|
117
|
+
(from [cimprofiles](https://github.com/PNNL-CIM-Tools/CIM-Profiles), through cim-graph) and accepts exactly
|
|
118
|
+
what that profile defines: its classes, attributes, associations and enumeration values. A new class in a new
|
|
119
|
+
profile works with no change here, and nothing outside the profile gets in. `Profile = cim18v17` names which
|
|
120
|
+
profile a file is written against.
|
|
121
|
+
- **One row is one CIM object.** A row is what an `rdf:about` block is in CIM XML; a cell is one property; a
|
|
122
|
+
reference cell names its target, as `rdf:resource` does.
|
|
123
|
+
- **Identity is CIM identity.** Objects are named by `mRID`, unique across the whole model as CIM 18 requires.
|
|
124
|
+
Each object's UUID is derived from its mRID and the model's `Authority` and `Model`, so loading the same file
|
|
125
|
+
twice gives the same UUIDs, two models can share a bus called `671` without colliding, and renaming an object
|
|
126
|
+
(`name`) never changes its identity.
|
|
127
|
+
- **Units are CIM units.** Values are stored as CIM's own unit types in SI, exactly as CIM XML holds them. The
|
|
128
|
+
`(unit)` on a column header only says what you typed. `pu` and `percent` impedances are converted to ohms
|
|
129
|
+
against the equipment's own rating (a transformer winding) or the system base (a line), and the system base is
|
|
130
|
+
the model's `BasePower` object, not a hidden default.
|
|
131
|
+
- **Define, then add.** `Object` and `Table` define objects; `Update` adds properties to an object defined
|
|
132
|
+
earlier, possibly in another file. That is CIM's formative and additive split, and how RDF adds properties to
|
|
133
|
+
an existing `rdf:about`.
|
|
134
|
+
- **The shorthand expands into normative CIM.** The only columns that aren't CIM names are the connectivity and
|
|
135
|
+
phase conveniences: `node`/`node1`/`node2` (ConnectivityNode), `bus`/`bus1`/`bus2` (TopologicalNode) and
|
|
136
|
+
`phases`. They generate standard Terminals, nodes and per-phase objects following the CIM rules (delta loads
|
|
137
|
+
included). They are optional: you can write `Terminal` and `ConnectivityNode` rows yourself, and a real CIM
|
|
138
|
+
attribute with the same name always wins.
|
|
139
|
+
- **Nothing hidden.** Everything that affects the model is in the text: the profile, the model identity, the
|
|
140
|
+
base power. The same file gives the same model on any machine.
|
|
141
|
+
|
|
142
|
+
## Writing a `.cimtbl` file
|
|
143
|
+
|
|
144
|
+
The whole format, briefly:
|
|
145
|
+
|
|
146
|
+
- **`Object <Class>: attribute=value, ...`** for a single object; **`Table <Class>: column, column, ...`**
|
|
147
|
+
followed by indented rows for many.
|
|
148
|
+
- **`#`** starts a comment. Blank lines don't matter.
|
|
149
|
+
- **A blank cell is unset.** Cells are trimmed. A value containing `,` `#` `(` or `)`, or with leading or
|
|
150
|
+
trailing spaces, is quoted as in CSV: `"#2_ACSR_6/1"`, `"DEFAULT (DC)"`. Source names are kept exactly as
|
|
151
|
+
written.
|
|
152
|
+
- **Units go on the column header**, `length (ft)`. A unit-bearing column with no unit is read in SI.
|
|
153
|
+
- **A header column can carry a default** for every row, `EquipmentContainer=fdr`. A row may override it by
|
|
154
|
+
adding a cell at the end.
|
|
155
|
+
- **References are by mRID, and the target must come first.** Declare `BaseVoltage bv_12kv` before the lines
|
|
156
|
+
that use it. Order your file the way you'd explain the model: bases and catalogs, then equipment.
|
|
157
|
+
- **`Import other.cimtbl`** splices another file in at that point, relative to the importing file. Use it to
|
|
158
|
+
share wire and transformer catalogs between models.
|
|
159
|
+
- **The same class can appear in several tables** with different columns, for example lines given by
|
|
160
|
+
impedance in one table and by catalog reference in another.
|
|
161
|
+
- **Phases are written in conductor order**: `ABCN`, `CB`, `s1s2N`. Leave `phases` blank for a balanced
|
|
162
|
+
three-phase device: CIM reads a Terminal with no phases as ABC.
|
|
163
|
+
|
|
164
|
+
The full format, including connectivity, phases, delta connections, relative impedance bases and the error
|
|
165
|
+
rules, is in [docs/CIMTBL_DESIGN.md](https://github.com/PNNL-CIM-Tools/CIM-Tables/blob/main/docs/CIMTBL_DESIGN.md).
|
|
166
|
+
|
|
167
|
+
## When something is wrong
|
|
168
|
+
|
|
169
|
+
Each row is checked against the profile before it touches the model, and every error names the file and line:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
tiny_feeder.cimtbl:21: EnergyConsumerRow has no attribute 'qq' - did you mean 'q'?
|
|
173
|
+
tiny_feeder.cimtbl:14: 'source': BaseVoltage 'bv_13kv' (BaseVoltage) not found in graph (declare it before rows that reference it)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Syntax errors, unknown classes and columns, values of the wrong type, references to undeclared objects,
|
|
177
|
+
duplicate mRIDs and missing ratings all fail the same way, at the line that caused them. Loading stops at the
|
|
178
|
+
first error: nothing is skipped and nothing is guessed.
|
|
179
|
+
|
|
180
|
+
## Installing
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
pip install --pre cim-tables
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`cim-tables` (imported as `cimtables`) is an alpha release and depends on pre-release versions of `cim-graph` and `cim-profiles`, hence
|
|
187
|
+
`--pre`. It needs Python 3.10 or newer.
|
|
188
|
+
|
|
189
|
+
## Using it from Python
|
|
190
|
+
|
|
191
|
+
- **`cimtables.load_model(path)`** builds a new model from a file: a `FeederModel` if the file has one
|
|
192
|
+
`Feeder`, else a `NodeBreakerModel` (for a single `Substation`, or no container at all).
|
|
193
|
+
`load_model(path, model_cls=BusBranchModel)` builds a bus-branch model instead.
|
|
194
|
+
- **`cimtables.load(path, network)`** adds a file's objects to a cim-graph model you already have, and
|
|
195
|
+
`load_text(text, network)` does the same for a string.
|
|
196
|
+
- **`cimtables.to_documents(model, name)`** turns any cim-graph model (one read from CIM XML, say) into
|
|
197
|
+
`.cimtbl`; `cimtables.document.write_documents(documents, directory)` writes the files. Loading them back
|
|
198
|
+
gives an equal model. By default an equipment's Terminals and per-phase objects are folded into its `node1`,
|
|
199
|
+
`node2` and `phases` columns, which renames them to `<mRID>_T1` and `<mRID>_A` (their UUIDs change too);
|
|
200
|
+
`terminals='explicit'` keeps every Terminal as its own row with its mRID. Units are picked per column (kV,
|
|
201
|
+
kW, ohm/km, ...); `units={'ACLineSegment.length': 'ft', 'PowerTransformerEnd.x': 'percent'}` (or a JSON
|
|
202
|
+
file of the same) fixes them, and `parts={'catalog': ['WireInfo', ...]}` splits classes into imported files.
|
|
203
|
+
- **`cimtables.document`** writes `.cimtbl` files from Python with stable, aligned formatting. Model converters
|
|
204
|
+
use it to produce `.cimtbl` that a person can then read and edit.
|
|
205
|
+
- Once loaded, the model is ordinary cim-graph: query it, modify it, and write it out with cim-graph's
|
|
206
|
+
`write_xml` or `write_json_ld`.
|
|
207
|
+
|
|
208
|
+
Two settings are process-wide, as they are in cim-graph: `load_model` sets the active CIM profile
|
|
209
|
+
(`CIMG_CIM_PROFILE`) from the file's `Profile =`, and both `load` and `load_model` set cim-graph's model scope
|
|
210
|
+
from `Authority =` and `Model =`.
|
|
211
|
+
|
|
212
|
+
## Where it fits
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
cimprofiles → cim-graph → cimtables → CIM-Builder, CIMHub
|
|
216
|
+
(the CIM (the model (.cimtbl in) (model builders and
|
|
217
|
+
classes) in memory) format converters)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
- [CIM-Profiles](https://github.com/PNNL-CIM-Tools/CIM-Profiles) provides the CIM classes and units.
|
|
221
|
+
- [CIM-Graph](https://github.com/PNNL-CIM-Tools/CIM-Graph) holds the model and reads and writes CIM XML and
|
|
222
|
+
JSON-LD.
|
|
223
|
+
- [CIM-Builder](https://github.com/PNNL-CIM-Tools/CIM-Builder) builds models programmatically on top of
|
|
224
|
+
`cimtables`.
|
|
225
|
+
- CIMHub's importers (OpenDSS and CYME so far) translate their native format into `.cimtbl` first, so the
|
|
226
|
+
converted model is something a person can read and check.
|
|
227
|
+
- [CIMTBL-Models](https://github.com/PNNL-CIM-Tools/CIMTBL-Models) is a library of grid models written in
|
|
228
|
+
`.cimtbl`.
|
|
229
|
+
|
|
230
|
+
## Status
|
|
231
|
+
|
|
232
|
+
This is an early release.
|
|
233
|
+
|
|
234
|
+
- The CIM 18 profile `cim18v17` is the one that is tested. Other profiles work in principle, because nothing
|
|
235
|
+
here is profile-specific, but they are not yet covered by tests.
|
|
236
|
+
- References must point backwards in the file. Forward references are an open question.
|
|
237
|
+
- A written model's UUIDs are seeded from its mRIDs, as for any `.cimtbl`: a CIM XML object whose UUID isn't
|
|
238
|
+
its mRID's gets a new one.
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
BSD 3-Clause; see [LICENSE](https://github.com/PNNL-CIM-Tools/CIM-Tables/blob/main/LICENSE) and [DISCLAIMER.md](https://github.com/PNNL-CIM-Tools/CIM-Tables/blob/main/DISCLAIMER.md). Copyright Battelle Memorial Institute.
|
|
243
|
+
Developed at Pacific Northwest National Laboratory.
|