grid-data-models 2.3.1__tar.gz → 2.3.3__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.
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/.gitignore +3 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/PKG-INFO +6 -5
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/README.md +1 -1
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/pyproject.toml +4 -3
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/cli/reducer.py +5 -3
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/base/distribution_branch_base.py +0 -9
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/distribution_system.py +29 -9
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/enums.py +16 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/phase_capacitor_equipment.py +13 -4
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/market/tariff.py +34 -7
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/model_reduction/reducer.py +41 -17
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/sys_functools.py +61 -46
- grid_data_models-2.3.3/src/gdm/distribution/upgrade_handler/from__2_3_1__to__2_3_2.py +15 -0
- grid_data_models-2.3.3/src/gdm/distribution/upgrade_handler/from__2_3_2__to__2_3_3.py +77 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/upgrade_handler.py +12 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/exceptions.py +9 -4
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/server.py +436 -82
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/version.py +1 -1
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/LICENSE.txt +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/cli/cli.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/constants.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/dataset/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/dataset/cost_model.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/dataset/dataset_system.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/catalog_system.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/common/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/common/curve.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/common/limitset.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/common/sequence_pair.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/base/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/base/distribution_component_base.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/base/distribution_switch_base.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/base/distribution_transformer_base.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_battery.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_bus.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_capacitor.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_feeder.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_load.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_regulator.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_solar.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_substation.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_transformer.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/distribution_vsource.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/geometry_branch.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/matrix_impedance_branch.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/matrix_impedance_fuse.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/matrix_impedance_recloser.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/matrix_impedance_switch.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/components/sequence_impedance_branch.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/base/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/base/capacitor_controller_base.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/base/inverter_controller_base.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/distribution_capacitor_controller.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/distribution_inverter_controller.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/distribution_recloser_controller.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/distribution_regulator_controller.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/controllers/distribution_switch_controller.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/distribution_graph.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/bare_conductor_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/base/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/base/matrix_impedance_branch_equipment_base.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/battery_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/capacitor_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/concentric_cable_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/distribution_transformer_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/geometry_branch_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/inverter_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/load_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/matrix_impedance_branch_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/matrix_impedance_fuse_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/matrix_impedance_recloser_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/matrix_impedance_switch_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/phase_load_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/phase_voltagesource_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/recloser_controller_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/sequence_impedance_branch_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/solar_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/equipment/voltagesource_equipment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/market/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/model_reduction/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/from__2_0_1__to__2_1_2.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/from__2_1_2__to__2_1_3.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/from__2_1_3__to__2_1_4.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/from__2_1_4__to__2_1_5.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/from__2_1_5__to__2_2_0.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/from__2_2_0__to__2_2_1.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/from__2_2_1__to__2_3_0.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/upgrade_handler/from__2_3_0__to__2_3_1.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/hashing_utils.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/exceptions.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/inspection/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/inspection/inspector.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/inspection/relationships.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/inspection/topology.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/knowledge/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/knowledge/documentation.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/operations/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/operations/merger.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/operations/splitter.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/schemas.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/utilities/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/utilities/subsystem.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/utilities/timeseries.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/validation/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/validation/auto_fixer.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/validation/diagnostics.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/validation/suggestions.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/mcp/version.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/quantities.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/__init__.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/base.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/building.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/overhead_line_segment.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/pole.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/pvsystem.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/transformer.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/underground_cable.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/components/underground_junction.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/structural/structural_system.py +0 -0
- {grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/tracked_changes.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: grid-data-models
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.3
|
|
4
4
|
Project-URL: Documentation, https://github.com/NREL-Distribution-Suites/grid-data-models#readme
|
|
5
5
|
Project-URL: Issues, https://github.com/NREL-Distribution-Suites/grid-data-models/issues
|
|
6
6
|
Project-URL: Source, https://github.com/NREL-Distribution-Suites/grid-data-models
|
|
@@ -13,9 +13,9 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
13
13
|
Requires-Python: >=3.11
|
|
14
14
|
Requires-Dist: geopandas
|
|
15
15
|
Requires-Dist: importlib-metadata
|
|
16
|
-
Requires-Dist: infrasys~=1.
|
|
16
|
+
Requires-Dist: infrasys~=1.1
|
|
17
17
|
Requires-Dist: networkx
|
|
18
|
-
Requires-Dist: pandas~=
|
|
18
|
+
Requires-Dist: pandas~=3.0.2
|
|
19
19
|
Requires-Dist: plotly
|
|
20
20
|
Requires-Dist: pydantic
|
|
21
21
|
Requires-Dist: semver
|
|
@@ -30,12 +30,13 @@ Requires-Dist: pytest-doctestplus; extra == 'dev'
|
|
|
30
30
|
Requires-Dist: ruff; extra == 'dev'
|
|
31
31
|
Provides-Extra: doc
|
|
32
32
|
Requires-Dist: autodoc-pydantic[erdantic]; extra == 'doc'
|
|
33
|
+
Requires-Dist: jupyter-book<3,>=2.1.4; extra == 'doc'
|
|
33
34
|
Requires-Dist: myst-parser; extra == 'doc'
|
|
34
35
|
Requires-Dist: pydata-sphinx-theme; extra == 'doc'
|
|
35
36
|
Requires-Dist: sphinx; extra == 'doc'
|
|
36
37
|
Requires-Dist: sphinxcontrib-mermaid; extra == 'doc'
|
|
37
38
|
Provides-Extra: mcp
|
|
38
|
-
Requires-Dist: mcp>=1.
|
|
39
|
+
Requires-Dist: mcp>=1.27.0; extra == 'mcp'
|
|
39
40
|
Description-Content-Type: text/markdown
|
|
40
41
|
|
|
41
42
|
|
|
@@ -61,7 +62,7 @@ In an effort to reduce code duplication and provide client packages a standard i
|
|
|
61
62
|
- **Built-in validation layer:** Use of [pydantic](https://docs.pydantic.dev/latest/) allows us to validate model fields.
|
|
62
63
|
- **Time series data management:** GDM uses [infrasys](https://github.nrel.gov/CADET/infrastructure_systems) package which enables [efficient time series data management](https://nrel.github.io/infrasys/explanation/time_series.html) by sharing arrays across components and offloading system memory. For example, we can attach time series power consumption data to a load profile.
|
|
63
64
|
- **Built-in unit conversion:** GDM leverages [pint](https://pint.readthedocs.io/en/stable/) for unit conversion for power system quantities. For example, power, voltage, time, etc.
|
|
64
|
-
- **JSON serialization/deserialization:** GDM uses [infrasys](https://github.com/
|
|
65
|
+
- **JSON serialization/deserialization:** GDM uses [infrasys](https://github.com/NatLabRockies/infrasys) to serialize and deserialize distribution system components to/from JSON.
|
|
65
66
|
- **Track System Changes:** Supports tracking changes within a distribution model (both temporal and scenario-based static updates), enabling powerful scenario management capabilities.
|
|
66
67
|
- **Graph-Based Analysis:** Exposes a connectivity graph using NetworkX, allowing advanced graph-based algorithms and visualizations.
|
|
67
68
|
- **Interoperability:** Easily integrates with existing tools.
|
|
@@ -21,7 +21,7 @@ In an effort to reduce code duplication and provide client packages a standard i
|
|
|
21
21
|
- **Built-in validation layer:** Use of [pydantic](https://docs.pydantic.dev/latest/) allows us to validate model fields.
|
|
22
22
|
- **Time series data management:** GDM uses [infrasys](https://github.nrel.gov/CADET/infrastructure_systems) package which enables [efficient time series data management](https://nrel.github.io/infrasys/explanation/time_series.html) by sharing arrays across components and offloading system memory. For example, we can attach time series power consumption data to a load profile.
|
|
23
23
|
- **Built-in unit conversion:** GDM leverages [pint](https://pint.readthedocs.io/en/stable/) for unit conversion for power system quantities. For example, power, voltage, time, etc.
|
|
24
|
-
- **JSON serialization/deserialization:** GDM uses [infrasys](https://github.com/
|
|
24
|
+
- **JSON serialization/deserialization:** GDM uses [infrasys](https://github.com/NatLabRockies/infrasys) to serialize and deserialize distribution system components to/from JSON.
|
|
25
25
|
- **Track System Changes:** Supports tracking changes within a distribution model (both temporal and scenario-based static updates), enabling powerful scenario management capabilities.
|
|
26
26
|
- **Graph-Based Analysis:** Exposes a connectivity graph using NetworkX, allowing advanced graph-based algorithms and visualizations.
|
|
27
27
|
- **Interoperability:** Easily integrates with existing tools.
|
|
@@ -24,18 +24,19 @@ dependencies = [
|
|
|
24
24
|
"semver",
|
|
25
25
|
"networkx",
|
|
26
26
|
"pydantic",
|
|
27
|
-
"infrasys~=1.
|
|
27
|
+
"infrasys~=1.1",
|
|
28
28
|
"importlib_metadata",
|
|
29
29
|
"typer",
|
|
30
|
-
"pandas~=
|
|
30
|
+
"pandas~=3.0.2",
|
|
31
31
|
"geopandas",
|
|
32
32
|
"plotly",
|
|
33
33
|
]
|
|
34
34
|
|
|
35
35
|
[project.optional-dependencies]
|
|
36
|
-
mcp = ["mcp>=1.
|
|
36
|
+
mcp = ["mcp>=1.27.0"]
|
|
37
37
|
dev = ["pre-commit", "pytest", "pytest-cov", "pytest-doctestplus", "pytest-asyncio", "ruff", "docutils"]
|
|
38
38
|
doc = [
|
|
39
|
+
"jupyter-book>=2.1.4,<3",
|
|
39
40
|
"sphinx",
|
|
40
41
|
"pydata-sphinx-theme",
|
|
41
42
|
"myst-parser",
|
|
@@ -28,9 +28,11 @@ def reduce(
|
|
|
28
28
|
reducer: Annotated[
|
|
29
29
|
ReducerType, typer.Option("-r", "--reducer", help="Reducer type to apply.")
|
|
30
30
|
] = ReducerType.three_phase,
|
|
31
|
-
|
|
31
|
+
time_series: Annotated[
|
|
32
32
|
bool,
|
|
33
|
-
typer.Option(
|
|
33
|
+
typer.Option(
|
|
34
|
+
"-ts", "--time-series", help="Include time series data in the reduced system."
|
|
35
|
+
),
|
|
34
36
|
] = False,
|
|
35
37
|
):
|
|
36
38
|
"""Reduce a GDM distribution system."""
|
|
@@ -46,6 +48,6 @@ def reduce(
|
|
|
46
48
|
sys = DistributionSystem.from_json(gdm_file)
|
|
47
49
|
reducer_func = {"three_phase": reduce_to_three_phase_system}
|
|
48
50
|
new_sys_name = sys.name + "_reduced" if sys.name else None
|
|
49
|
-
new_sys = reducer_func[reducer.value](sys, new_sys_name,
|
|
51
|
+
new_sys = reducer_func[reducer.value](sys, new_sys_name, time_series)
|
|
50
52
|
new_sys.to_json(target_path)
|
|
51
53
|
typer.echo(str(target_path))
|
|
@@ -41,15 +41,6 @@ class DistributionBranchBase(InServiceDistributionComponentBase, ABC):
|
|
|
41
41
|
msg = f"Conductor phase ({phase=}) does not match bus phases ({bus.phases=})"
|
|
42
42
|
raise ValueError(msg)
|
|
43
43
|
|
|
44
|
-
num_branch_phases = len(self.phases)
|
|
45
|
-
if not any(num_branch_phases == len(bus.phases) for bus in self.buses):
|
|
46
|
-
bus_phase_counts = {bus.name: len(bus.phases) for bus in self.buses}
|
|
47
|
-
msg = (
|
|
48
|
-
f"Number of branch phases ({num_branch_phases}) must match the number of phases "
|
|
49
|
-
f"of at least one connected bus. Connected bus phase counts: {bus_phase_counts}"
|
|
50
|
-
)
|
|
51
|
-
raise ValueError(msg)
|
|
52
|
-
|
|
53
44
|
if self.buses[0].name == self.buses[1].name:
|
|
54
45
|
msg = (
|
|
55
46
|
f"From bus {self.buses[0].name=} and to bus"
|
{grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/distribution_system.py
RENAMED
|
@@ -276,8 +276,10 @@ class DistributionSystem(System):
|
|
|
276
276
|
self,
|
|
277
277
|
bus_names: list[str],
|
|
278
278
|
name: str,
|
|
279
|
-
|
|
279
|
+
keep_time_series: bool = False,
|
|
280
|
+
keep_timeseries: bool | None = None,
|
|
280
281
|
time_series_type: Type[TimeSeriesData] = SingleTimeSeries,
|
|
282
|
+
directed_graph: nx.DiGraph | None = None,
|
|
281
283
|
) -> "DistributionSystem":
|
|
282
284
|
"""Method to get subsystem from list of buses.
|
|
283
285
|
|
|
@@ -287,15 +289,23 @@ class DistributionSystem(System):
|
|
|
287
289
|
List of bus names
|
|
288
290
|
name: str
|
|
289
291
|
Name of the subsystem.
|
|
290
|
-
|
|
291
|
-
Set this flag to retain
|
|
292
|
+
keep_time_series: bool
|
|
293
|
+
Set this flag to retain time series data associated with the component.
|
|
294
|
+
keep_timeseries: bool | None
|
|
295
|
+
Deprecated alias for keep_time_series.
|
|
292
296
|
time_series_type: Type[TimeSeriesData]
|
|
293
297
|
Type of time series data. Defaults to: SingleTimeSeries
|
|
298
|
+
directed_graph: nx.DiGraph | None
|
|
299
|
+
Optional precomputed directed graph for this system. When provided,
|
|
300
|
+
it is reused instead of rebuilding the directed graph.
|
|
294
301
|
Returns
|
|
295
302
|
-------
|
|
296
303
|
DistributionSystem
|
|
297
304
|
"""
|
|
298
|
-
|
|
305
|
+
if keep_timeseries is not None:
|
|
306
|
+
keep_time_series = keep_timeseries
|
|
307
|
+
|
|
308
|
+
tree = directed_graph if directed_graph is not None else self.get_directed_graph()
|
|
299
309
|
subtree = tree.subgraph(bus_names)
|
|
300
310
|
subtree_system = DistributionSystem(auto_add_composed_components=True, name=name)
|
|
301
311
|
for u, v, _ in subtree.edges(data=True):
|
|
@@ -308,7 +318,7 @@ class DistributionSystem(System):
|
|
|
308
318
|
parent_components = self.list_parent_components(self.get_component(DistributionBus, u))
|
|
309
319
|
self._add_to_subsystem(subtree_system, parent_components, bus_names)
|
|
310
320
|
|
|
311
|
-
if
|
|
321
|
+
if keep_time_series:
|
|
312
322
|
for comp in subtree_system.get_components(
|
|
313
323
|
Component,
|
|
314
324
|
filter_func=lambda x: self.has_time_series(x, time_series_type=time_series_type),
|
|
@@ -470,7 +480,6 @@ class DistributionSystem(System):
|
|
|
470
480
|
bus_1 = cycle[i]
|
|
471
481
|
bus_2 = cycle[(i + 1) % len(cycle)]
|
|
472
482
|
edge_data = self.get_undirected_graph().get_edge_data(bus_1, bus_2)
|
|
473
|
-
print(bus_1, bus_2, edge_data)
|
|
474
483
|
if edge_data:
|
|
475
484
|
for key, data in edge_data.items():
|
|
476
485
|
if issubclass(data.get("type"), MatrixImpedanceSwitch):
|
|
@@ -480,7 +489,10 @@ class DistributionSystem(System):
|
|
|
480
489
|
break
|
|
481
490
|
return list(set(switch_buses))
|
|
482
491
|
|
|
483
|
-
def get_split_phase_mapping(
|
|
492
|
+
def get_split_phase_mapping(
|
|
493
|
+
self,
|
|
494
|
+
directed_graph: nx.DiGraph | None = None,
|
|
495
|
+
) -> dict[str, set[Phase]]:
|
|
484
496
|
"""Generates a mapping of components to their split-phase configurations.
|
|
485
497
|
|
|
486
498
|
This method identifies distribution transformers with center-tapped windings and
|
|
@@ -494,6 +506,12 @@ class DistributionSystem(System):
|
|
|
494
506
|
A dictionary where keys are component names and values are sets of phases
|
|
495
507
|
associated with the high-voltage bus.
|
|
496
508
|
|
|
509
|
+
Parameters
|
|
510
|
+
----------
|
|
511
|
+
directed_graph: nx.DiGraph | None
|
|
512
|
+
Optional precomputed directed graph for this system. When provided,
|
|
513
|
+
it is reused instead of rebuilding the directed graph.
|
|
514
|
+
|
|
497
515
|
Notes
|
|
498
516
|
-----
|
|
499
517
|
- The method uses the directed graph representation of the distribution system to
|
|
@@ -505,7 +523,7 @@ class DistributionSystem(System):
|
|
|
505
523
|
- Logs the process of identifying and mapping split-phase transformers.
|
|
506
524
|
"""
|
|
507
525
|
split_phase_map = {}
|
|
508
|
-
original_tree = self.get_directed_graph()
|
|
526
|
+
original_tree = directed_graph if directed_graph is not None else self.get_directed_graph()
|
|
509
527
|
split_phase_trs: list[DistributionTransformer] = list(
|
|
510
528
|
self.get_components(
|
|
511
529
|
DistributionTransformer,
|
|
@@ -518,7 +536,9 @@ class DistributionSystem(System):
|
|
|
518
536
|
}.pop()
|
|
519
537
|
hv_bus = (set([bus.name for bus in tr.buses]) - set([lv_bus])).pop()
|
|
520
538
|
lv_system = self.get_subsystem(
|
|
521
|
-
list(nx.descendants(original_tree, lv_bus)) + [lv_bus],
|
|
539
|
+
list(nx.descendants(original_tree, lv_bus)) + [lv_bus],
|
|
540
|
+
name="",
|
|
541
|
+
directed_graph=original_tree,
|
|
522
542
|
)
|
|
523
543
|
bus_model_types = self.get_model_types_with_field_type(DistributionBus)
|
|
524
544
|
for model_type in bus_model_types:
|
|
@@ -118,6 +118,21 @@ class TOUPeriodType(str, Enum):
|
|
|
118
118
|
MID_PEAK = "mid_peak"
|
|
119
119
|
|
|
120
120
|
|
|
121
|
+
class Month(str, Enum):
|
|
122
|
+
JANUARY = "january"
|
|
123
|
+
FEBRUARY = "february"
|
|
124
|
+
MARCH = "march"
|
|
125
|
+
APRIL = "april"
|
|
126
|
+
MAY = "may"
|
|
127
|
+
JUNE = "june"
|
|
128
|
+
JULY = "july"
|
|
129
|
+
AUGUST = "august"
|
|
130
|
+
SEPTEMBER = "september"
|
|
131
|
+
OCTOBER = "october"
|
|
132
|
+
NOVEMBER = "november"
|
|
133
|
+
DECEMBER = "december"
|
|
134
|
+
|
|
135
|
+
|
|
121
136
|
class Season(str, Enum):
|
|
122
137
|
SUMMER = "summer"
|
|
123
138
|
WINTER = "winter"
|
|
@@ -128,6 +143,7 @@ class CustomerClass(str, Enum):
|
|
|
128
143
|
RESIDENTIAL = "residential"
|
|
129
144
|
COMMERCIAL = "commercial"
|
|
130
145
|
INDUSTRIAL = "industrial"
|
|
146
|
+
UTILITY = "utility"
|
|
131
147
|
|
|
132
148
|
|
|
133
149
|
class BillingDemandBasis(str, Enum):
|
|
@@ -54,13 +54,22 @@ class PhaseCapacitorEquipment(Component):
|
|
|
54
54
|
def aggregate(
|
|
55
55
|
cls, instances: list["PhaseCapacitorEquipment"], name: str
|
|
56
56
|
) -> "PhaseCapacitorEquipment":
|
|
57
|
+
resistance_inverse_sum = sum(
|
|
58
|
+
1 / inst.resistance for inst in instances if inst.resistance.magnitude
|
|
59
|
+
)
|
|
60
|
+
reactance_inverse_sum = sum(
|
|
61
|
+
1 / inst.reactance for inst in instances if inst.reactance.magnitude
|
|
62
|
+
)
|
|
63
|
+
|
|
57
64
|
return PhaseCapacitorEquipment(
|
|
58
65
|
name=name,
|
|
59
66
|
rated_reactive_power=sum(inst.rated_reactive_power for inst in instances),
|
|
60
|
-
resistance=
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
resistance=(
|
|
68
|
+
1 / resistance_inverse_sum if resistance_inverse_sum else Resistance(0, "ohm")
|
|
69
|
+
),
|
|
70
|
+
reactance=(
|
|
71
|
+
1 / reactance_inverse_sum if reactance_inverse_sum else Reactance(0, "ohm")
|
|
72
|
+
),
|
|
64
73
|
num_banks=sum(inst.num_banks for inst in instances),
|
|
65
74
|
num_banks_on=sum(inst.num_banks_on for inst in instances),
|
|
66
75
|
)
|
|
@@ -4,7 +4,7 @@ from pydantic import Field, model_validator
|
|
|
4
4
|
from typing import List, Optional
|
|
5
5
|
from infrasys import Component
|
|
6
6
|
|
|
7
|
-
from gdm.distribution.enums import BillingDemandBasis, CustomerClass,
|
|
7
|
+
from gdm.distribution.enums import BillingDemandBasis, CustomerClass, Month, TOUPeriodType
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class TOURatePeriod(Component):
|
|
@@ -31,6 +31,9 @@ class TOURatePeriod(Component):
|
|
|
31
31
|
|
|
32
32
|
class DemandCharge(Component):
|
|
33
33
|
name: str = ""
|
|
34
|
+
months: List[Month] = Field(
|
|
35
|
+
..., min_length=1, description="Months for which this demand charge applies"
|
|
36
|
+
)
|
|
34
37
|
rate: float = Field(..., gt=0, description="Rate for demand charge in $/kW")
|
|
35
38
|
billing_demand_basis: BillingDemandBasis = Field(
|
|
36
39
|
..., description="Basis for billing demand calculation"
|
|
@@ -39,9 +42,16 @@ class DemandCharge(Component):
|
|
|
39
42
|
..., description="Time periods when the demand charge applies"
|
|
40
43
|
)
|
|
41
44
|
|
|
45
|
+
@model_validator(mode="after")
|
|
46
|
+
def check_no_duplicate_months(self) -> "DemandCharge":
|
|
47
|
+
if len(self.months) != len(set(self.months)):
|
|
48
|
+
raise ValueError("Duplicate months are not allowed within a single DemandCharge")
|
|
49
|
+
return self
|
|
50
|
+
|
|
42
51
|
@classmethod
|
|
43
52
|
def example(cls) -> "DemandCharge":
|
|
44
53
|
return DemandCharge(
|
|
54
|
+
months=[Month.JUNE, Month.JULY, Month.AUGUST],
|
|
45
55
|
rate=12.50,
|
|
46
56
|
billing_demand_basis=BillingDemandBasis.PEAK_15MIN,
|
|
47
57
|
time_applicability=[TOURatePeriod.example()],
|
|
@@ -50,13 +60,23 @@ class DemandCharge(Component):
|
|
|
50
60
|
|
|
51
61
|
class SeasonalTOURates(Component):
|
|
52
62
|
name: str = ""
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
months: List[Month] = Field(
|
|
64
|
+
..., min_length=1, description="Months for which these TOU rates apply"
|
|
65
|
+
)
|
|
66
|
+
tou_periods: List[TOURatePeriod] = Field(
|
|
67
|
+
..., description="List of TOU periods for the specified months"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
@model_validator(mode="after")
|
|
71
|
+
def check_no_duplicate_months(self) -> "SeasonalTOURates":
|
|
72
|
+
if len(self.months) != len(set(self.months)):
|
|
73
|
+
raise ValueError("Duplicate months are not allowed within a single SeasonalTOURates")
|
|
74
|
+
return self
|
|
55
75
|
|
|
56
76
|
@classmethod
|
|
57
77
|
def example(cls) -> "SeasonalTOURates":
|
|
58
78
|
return SeasonalTOURates(
|
|
59
|
-
|
|
79
|
+
months=[Month.JUNE, Month.JULY, Month.AUGUST],
|
|
60
80
|
tou_periods=[
|
|
61
81
|
TOURatePeriod.example(),
|
|
62
82
|
TOURatePeriod(
|
|
@@ -81,7 +101,7 @@ class TieredRate(Component):
|
|
|
81
101
|
|
|
82
102
|
class FixedCharge(Component):
|
|
83
103
|
name: str = ""
|
|
84
|
-
amount: float = Field(...,
|
|
104
|
+
amount: float = Field(..., ge=0, description="Amount of the fixed charge in $/month")
|
|
85
105
|
description: Optional[str] = Field(None, description="Description of the fixed charge")
|
|
86
106
|
|
|
87
107
|
@classmethod
|
|
@@ -93,7 +113,7 @@ class DistributionTariff(Component):
|
|
|
93
113
|
name: str = Field(..., description="Name of the tariff")
|
|
94
114
|
utility: str = Field(..., description="Name of the utility company")
|
|
95
115
|
customer_class: CustomerClass = Field(..., description="Customer class for the tariff")
|
|
96
|
-
fixed_charge: FixedCharge = Field(
|
|
116
|
+
fixed_charge: Optional[FixedCharge] = Field(None, description="Fixed charge for the tariff")
|
|
97
117
|
seasonal_tou: List[SeasonalTOURates] = Field(
|
|
98
118
|
..., description="Seasonal TOU rates for the tariff"
|
|
99
119
|
)
|
|
@@ -104,6 +124,13 @@ class DistributionTariff(Component):
|
|
|
104
124
|
None, description="List of tiered energy charges for the tariff"
|
|
105
125
|
)
|
|
106
126
|
|
|
127
|
+
@model_validator(mode="after")
|
|
128
|
+
def check_no_overlapping_months(self) -> "DistributionTariff":
|
|
129
|
+
all_months = [m for entry in self.seasonal_tou for m in entry.months]
|
|
130
|
+
if len(all_months) != len(set(all_months)):
|
|
131
|
+
raise ValueError("A month must not appear in more than one SeasonalTOURates entry")
|
|
132
|
+
return self
|
|
133
|
+
|
|
107
134
|
@classmethod
|
|
108
135
|
def example(cls) -> "DistributionTariff":
|
|
109
136
|
return DistributionTariff(
|
|
@@ -114,7 +141,7 @@ class DistributionTariff(Component):
|
|
|
114
141
|
seasonal_tou=[
|
|
115
142
|
SeasonalTOURates.example(),
|
|
116
143
|
SeasonalTOURates(
|
|
117
|
-
|
|
144
|
+
months=[Month.DECEMBER, Month.JANUARY, Month.FEBRUARY],
|
|
118
145
|
tou_periods=[
|
|
119
146
|
TOURatePeriod.example(),
|
|
120
147
|
TOURatePeriod(
|
{grid_data_models-2.3.1 → grid_data_models-2.3.3}/src/gdm/distribution/model_reduction/reducer.py
RENAMED
|
@@ -14,9 +14,9 @@ from gdm.distribution.distribution_system import (
|
|
|
14
14
|
)
|
|
15
15
|
from gdm.distribution.enums import Phase
|
|
16
16
|
from gdm.distribution.sys_functools import (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
get_aggregated_load_time_series,
|
|
18
|
+
get_aggregated_solar_time_series,
|
|
19
|
+
get_aggregated_battery_time_series,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
|
|
@@ -74,23 +74,28 @@ def _reduce_system(
|
|
|
74
74
|
dist_system: DistributionSystem,
|
|
75
75
|
bus_subset: list[DistributionBus],
|
|
76
76
|
name: str,
|
|
77
|
-
|
|
77
|
+
agg_time_series: bool = False,
|
|
78
|
+
agg_timeseries: bool | None = None,
|
|
78
79
|
time_series_type: Type[TimeSeriesData] = SingleTimeSeries,
|
|
79
80
|
) -> DistributionSystem:
|
|
81
|
+
if agg_timeseries is not None:
|
|
82
|
+
agg_time_series = agg_timeseries
|
|
83
|
+
|
|
84
|
+
original_tree = dist_system.get_directed_graph()
|
|
80
85
|
reduced_system = dist_system.get_subsystem(
|
|
81
86
|
bus_subset,
|
|
82
87
|
name,
|
|
83
|
-
|
|
88
|
+
keep_time_series=agg_time_series,
|
|
84
89
|
time_series_type=time_series_type,
|
|
90
|
+
directed_graph=original_tree,
|
|
85
91
|
)
|
|
86
92
|
|
|
87
|
-
split_phase_mapping = dist_system.get_split_phase_mapping()
|
|
88
|
-
original_tree = dist_system.get_directed_graph()
|
|
93
|
+
split_phase_mapping = dist_system.get_split_phase_mapping(directed_graph=original_tree)
|
|
89
94
|
reduced_network_tree = original_tree.subgraph(bus_subset)
|
|
90
95
|
ts_agg_func_mapper: dict[Union[Type[DistributionLoad], Type[DistributionSolar]], Callable] = {
|
|
91
|
-
DistributionLoad:
|
|
92
|
-
DistributionSolar:
|
|
93
|
-
DistributionBattery:
|
|
96
|
+
DistributionLoad: get_aggregated_load_time_series,
|
|
97
|
+
DistributionSolar: get_aggregated_solar_time_series,
|
|
98
|
+
DistributionBattery: get_aggregated_battery_time_series,
|
|
94
99
|
}
|
|
95
100
|
for node in reduced_network_tree.nodes():
|
|
96
101
|
if reduced_network_tree.out_degree(node) < original_tree.out_degree(node):
|
|
@@ -103,7 +108,11 @@ def _reduce_system(
|
|
|
103
108
|
for snode in nx.descendants(original_tree, successor)
|
|
104
109
|
] + list(sucessors_diff)
|
|
105
110
|
subtree = original_tree.subgraph(successors_descendants)
|
|
106
|
-
subtree_system = dist_system.get_subsystem(
|
|
111
|
+
subtree_system = dist_system.get_subsystem(
|
|
112
|
+
list(subtree.nodes),
|
|
113
|
+
"",
|
|
114
|
+
directed_graph=original_tree,
|
|
115
|
+
)
|
|
107
116
|
model_types = subtree_system.get_model_types_with_field_type(DistributionBus)
|
|
108
117
|
for model_type in model_types:
|
|
109
118
|
agg_component = _get_aggregated_bus_component(
|
|
@@ -112,10 +121,9 @@ def _reduce_system(
|
|
|
112
121
|
model_type=model_type,
|
|
113
122
|
split_phase_mapping=split_phase_mapping,
|
|
114
123
|
)
|
|
115
|
-
# print(model_type.__name__, agg_component)
|
|
116
124
|
reduced_system.add_component(agg_component)
|
|
117
125
|
agg_comp = reduced_system.get_component(model_type, agg_component.name)
|
|
118
|
-
if
|
|
126
|
+
if agg_time_series:
|
|
119
127
|
comps = list(subtree_system.get_components(model_type))
|
|
120
128
|
ts_metadata = dist_system.list_time_series_metadata(
|
|
121
129
|
comps[0], time_series_type=time_series_type
|
|
@@ -135,18 +143,34 @@ def _reduce_system(
|
|
|
135
143
|
def reduce_to_three_phase_system(
|
|
136
144
|
dist_system: DistributionSystem,
|
|
137
145
|
name: str,
|
|
138
|
-
|
|
146
|
+
agg_time_series: bool = False,
|
|
147
|
+
agg_timeseries: bool | None = None,
|
|
139
148
|
time_series_type: Type[TimeSeriesData] = SingleTimeSeries,
|
|
140
149
|
) -> DistributionSystem:
|
|
141
150
|
three_phase_buses = _get_three_phase_buses(dist_system)
|
|
142
|
-
return _reduce_system(
|
|
151
|
+
return _reduce_system(
|
|
152
|
+
dist_system,
|
|
153
|
+
three_phase_buses,
|
|
154
|
+
name,
|
|
155
|
+
agg_time_series,
|
|
156
|
+
agg_timeseries,
|
|
157
|
+
time_series_type,
|
|
158
|
+
)
|
|
143
159
|
|
|
144
160
|
|
|
145
161
|
def reduce_to_primary_system(
|
|
146
162
|
dist_system: DistributionSystem,
|
|
147
163
|
name: str,
|
|
148
|
-
|
|
164
|
+
agg_time_series: bool = False,
|
|
165
|
+
agg_timeseries: bool | None = None,
|
|
149
166
|
time_series_type: Type[TimeSeriesData] = SingleTimeSeries,
|
|
150
167
|
) -> DistributionSystem:
|
|
151
168
|
primary_buses = _get_primary_buses(dist_system)
|
|
152
|
-
return _reduce_system(
|
|
169
|
+
return _reduce_system(
|
|
170
|
+
dist_system,
|
|
171
|
+
primary_buses,
|
|
172
|
+
name,
|
|
173
|
+
agg_time_series,
|
|
174
|
+
agg_timeseries,
|
|
175
|
+
time_series_type,
|
|
176
|
+
)
|