grid-data-models 2.3.1__tar.gz → 2.3.2__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.
Files changed (127) hide show
  1. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/.gitignore +3 -0
  2. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/PKG-INFO +3 -2
  3. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/README.md +1 -1
  4. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/pyproject.toml +1 -0
  5. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/cli/reducer.py +5 -3
  6. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/base/distribution_branch_base.py +0 -9
  7. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/distribution_system.py +29 -9
  8. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/enums.py +15 -0
  9. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/phase_capacitor_equipment.py +13 -4
  10. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/market/tariff.py +5 -5
  11. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/model_reduction/reducer.py +41 -17
  12. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/sys_functools.py +61 -46
  13. grid_data_models-2.3.2/src/gdm/distribution/upgrade_handler/from__2_3_1__to__2_3_2.py +15 -0
  14. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/upgrade_handler.py +6 -0
  15. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/exceptions.py +9 -4
  16. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/server.py +436 -82
  17. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/version.py +1 -1
  18. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/LICENSE.txt +0 -0
  19. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/__init__.py +0 -0
  20. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/cli/cli.py +0 -0
  21. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/constants.py +0 -0
  22. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/dataset/__init__.py +0 -0
  23. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/dataset/cost_model.py +0 -0
  24. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/dataset/dataset_system.py +0 -0
  25. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/__init__.py +0 -0
  26. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/catalog_system.py +0 -0
  27. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/common/__init__.py +0 -0
  28. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/common/curve.py +0 -0
  29. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/common/limitset.py +0 -0
  30. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/common/sequence_pair.py +0 -0
  31. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/__init__.py +0 -0
  32. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/base/__init__.py +0 -0
  33. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/base/distribution_component_base.py +0 -0
  34. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/base/distribution_switch_base.py +0 -0
  35. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/base/distribution_transformer_base.py +0 -0
  36. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_battery.py +0 -0
  37. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_bus.py +0 -0
  38. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_capacitor.py +0 -0
  39. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_feeder.py +0 -0
  40. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_load.py +0 -0
  41. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_regulator.py +0 -0
  42. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_solar.py +0 -0
  43. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_substation.py +0 -0
  44. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_transformer.py +0 -0
  45. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/distribution_vsource.py +0 -0
  46. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/geometry_branch.py +0 -0
  47. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/matrix_impedance_branch.py +0 -0
  48. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/matrix_impedance_fuse.py +0 -0
  49. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/matrix_impedance_recloser.py +0 -0
  50. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/matrix_impedance_switch.py +0 -0
  51. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/components/sequence_impedance_branch.py +0 -0
  52. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/__init__.py +0 -0
  53. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/base/__init__.py +0 -0
  54. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/base/capacitor_controller_base.py +0 -0
  55. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/base/inverter_controller_base.py +0 -0
  56. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/distribution_capacitor_controller.py +0 -0
  57. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/distribution_inverter_controller.py +0 -0
  58. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/distribution_recloser_controller.py +0 -0
  59. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/distribution_regulator_controller.py +0 -0
  60. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/controllers/distribution_switch_controller.py +0 -0
  61. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/distribution_graph.py +0 -0
  62. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/__init__.py +0 -0
  63. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/bare_conductor_equipment.py +0 -0
  64. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/base/__init__.py +0 -0
  65. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/base/matrix_impedance_branch_equipment_base.py +0 -0
  66. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/battery_equipment.py +0 -0
  67. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/capacitor_equipment.py +0 -0
  68. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/concentric_cable_equipment.py +0 -0
  69. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/distribution_transformer_equipment.py +0 -0
  70. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/geometry_branch_equipment.py +0 -0
  71. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/inverter_equipment.py +0 -0
  72. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/load_equipment.py +0 -0
  73. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/matrix_impedance_branch_equipment.py +0 -0
  74. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/matrix_impedance_fuse_equipment.py +0 -0
  75. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/matrix_impedance_recloser_equipment.py +0 -0
  76. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/matrix_impedance_switch_equipment.py +0 -0
  77. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/phase_load_equipment.py +0 -0
  78. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/phase_voltagesource_equipment.py +0 -0
  79. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/recloser_controller_equipment.py +0 -0
  80. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/sequence_impedance_branch_equipment.py +0 -0
  81. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/solar_equipment.py +0 -0
  82. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/equipment/voltagesource_equipment.py +0 -0
  83. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/market/__init__.py +0 -0
  84. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/model_reduction/__init__.py +0 -0
  85. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/__init__.py +0 -0
  86. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/from__2_0_1__to__2_1_2.py +0 -0
  87. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/from__2_1_2__to__2_1_3.py +0 -0
  88. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/from__2_1_3__to__2_1_4.py +0 -0
  89. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/from__2_1_4__to__2_1_5.py +0 -0
  90. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/from__2_1_5__to__2_2_0.py +0 -0
  91. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/from__2_2_0__to__2_2_1.py +0 -0
  92. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/from__2_2_1__to__2_3_0.py +0 -0
  93. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/distribution/upgrade_handler/from__2_3_0__to__2_3_1.py +0 -0
  94. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/hashing_utils.py +0 -0
  95. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/__init__.py +0 -0
  96. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/exceptions.py +0 -0
  97. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/inspection/__init__.py +0 -0
  98. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/inspection/inspector.py +0 -0
  99. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/inspection/relationships.py +0 -0
  100. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/inspection/topology.py +0 -0
  101. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/knowledge/__init__.py +0 -0
  102. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/knowledge/documentation.py +0 -0
  103. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/operations/__init__.py +0 -0
  104. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/operations/merger.py +0 -0
  105. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/operations/splitter.py +0 -0
  106. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/schemas.py +0 -0
  107. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/utilities/__init__.py +0 -0
  108. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/utilities/subsystem.py +0 -0
  109. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/utilities/timeseries.py +0 -0
  110. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/validation/__init__.py +0 -0
  111. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/validation/auto_fixer.py +0 -0
  112. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/validation/diagnostics.py +0 -0
  113. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/validation/suggestions.py +0 -0
  114. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/mcp/version.py +0 -0
  115. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/quantities.py +0 -0
  116. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/__init__.py +0 -0
  117. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/__init__.py +0 -0
  118. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/base.py +0 -0
  119. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/building.py +0 -0
  120. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/overhead_line_segment.py +0 -0
  121. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/pole.py +0 -0
  122. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/pvsystem.py +0 -0
  123. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/transformer.py +0 -0
  124. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/underground_cable.py +0 -0
  125. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/components/underground_junction.py +0 -0
  126. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/structural/structural_system.py +0 -0
  127. {grid_data_models-2.3.1 → grid_data_models-2.3.2}/src/gdm/tracked_changes.py +0 -0
@@ -7,6 +7,8 @@ __pycache__/
7
7
  *.so
8
8
  *.code-workspace
9
9
  *.sqlite
10
+ *.db
11
+ *.sql
10
12
  *.ruff_cache/
11
13
 
12
14
  # Distribution / packaging
@@ -164,3 +166,4 @@ cython_debug/
164
166
  .qodo
165
167
  .DS_Store
166
168
  *.dump
169
+ uv.lock
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: grid-data-models
3
- Version: 2.3.1
3
+ Version: 2.3.2
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
@@ -30,6 +30,7 @@ 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; 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'
@@ -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/NREL/infrasys) to serialize and deserialize distribution system components to/from JSON.
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/NREL/infrasys) to serialize and deserialize distribution system components to/from JSON.
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.
@@ -36,6 +36,7 @@ dependencies = [
36
36
  mcp = ["mcp>=1.0.0"]
37
37
  dev = ["pre-commit", "pytest", "pytest-cov", "pytest-doctestplus", "pytest-asyncio", "ruff", "docutils"]
38
38
  doc = [
39
+ "jupyter-book>=2,<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
- timeseries: Annotated[
31
+ time_series: Annotated[
32
32
  bool,
33
- typer.Option("-ts", "--timeseries", help="Include timeseries data in the reduced system."),
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, timeseries)
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"
@@ -276,8 +276,10 @@ class DistributionSystem(System):
276
276
  self,
277
277
  bus_names: list[str],
278
278
  name: str,
279
- keep_timeseries: bool = False,
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
- keep_timeseries: bool
291
- Set this flag to retain timeseries data associated with the component.
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
- tree = self.get_directed_graph()
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 keep_timeseries:
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(self) -> dict[str, set[Phase]]:
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], name=""
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"
@@ -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=1
61
- / sum(1 / inst.resistance if inst.resistance.magnitude else 0 for inst in instances),
62
- reactance=1
63
- / sum(1 / inst.reactance if inst.reactance.magnitude else 0 for inst in instances),
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, TOUPeriodType, Season
7
+ from gdm.distribution.enums import BillingDemandBasis, CustomerClass, Month, TOUPeriodType
8
8
 
9
9
 
10
10
  class TOURatePeriod(Component):
@@ -50,13 +50,13 @@ class DemandCharge(Component):
50
50
 
51
51
  class SeasonalTOURates(Component):
52
52
  name: str = ""
53
- season: Season = Field(..., description="Season for the TOU rates")
54
- tou_periods: List[TOURatePeriod] = Field(..., description="List of TOU periods for the season")
53
+ season: Month = Field(..., description="Month for the TOU rates")
54
+ tou_periods: List[TOURatePeriod] = Field(..., description="List of TOU periods for the month")
55
55
 
56
56
  @classmethod
57
57
  def example(cls) -> "SeasonalTOURates":
58
58
  return SeasonalTOURates(
59
- season=Season.SUMMER,
59
+ season=Month.JULY,
60
60
  tou_periods=[
61
61
  TOURatePeriod.example(),
62
62
  TOURatePeriod(
@@ -114,7 +114,7 @@ class DistributionTariff(Component):
114
114
  seasonal_tou=[
115
115
  SeasonalTOURates.example(),
116
116
  SeasonalTOURates(
117
- season=Season.WINTER,
117
+ season=Month.JANUARY,
118
118
  tou_periods=[
119
119
  TOURatePeriod.example(),
120
120
  TOURatePeriod(
@@ -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
- get_aggregated_load_timeseries,
18
- get_aggregated_solar_timeseries,
19
- get_aggregated_battery_timeseries,
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
- agg_timeseries: bool = False,
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
- keep_timeseries=agg_timeseries,
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: get_aggregated_load_timeseries,
92
- DistributionSolar: get_aggregated_solar_timeseries,
93
- DistributionBattery: get_aggregated_battery_timeseries,
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(subtree.nodes, "")
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 agg_timeseries:
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
- agg_timeseries: bool = False,
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(dist_system, three_phase_buses, name, agg_timeseries, time_series_type)
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
- agg_timeseries: bool = False,
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(dist_system, primary_buses, name, agg_timeseries, time_series_type)
169
+ return _reduce_system(
170
+ dist_system,
171
+ primary_buses,
172
+ name,
173
+ agg_time_series,
174
+ agg_timeseries,
175
+ time_series_type,
176
+ )