From ccf1dcf931cf46dbf2c198b3d4c5c254eac5a336 Mon Sep 17 00:00:00 2001 From: Aadil Latif Date: Fri, 27 Feb 2026 11:59:28 -0700 Subject: [PATCH] bug fix --- .gitignore | 1 + distribution copy.sqlite3 | Bin 827392 -> 0 bytes distribution_schema.sql | 1288 ------------------- schema.sql | 367 ------ src/gdm/distribution/distribution_system.py | 33 + 5 files changed, 34 insertions(+), 1655 deletions(-) delete mode 100644 distribution copy.sqlite3 delete mode 100644 distribution_schema.sql delete mode 100644 schema.sql diff --git a/.gitignore b/.gitignore index a22d1f2a..b8b05482 100644 --- a/.gitignore +++ b/.gitignore @@ -163,3 +163,4 @@ cython_debug/ #.idea/ .qodo .DS_Store +*.dump diff --git a/distribution copy.sqlite3 b/distribution copy.sqlite3 deleted file mode 100644 index dfc3b1969a849cf4dea0c05b6c1a9f8692d343bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 827392 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%0AJM51Wwy^b+cZ% z63S-%IHGQmHd*(TE3wMQs#|RrR@eR$7C@X;1j^9~_M~IbF-D%pIq`08XnrwdzpXP}RZFNZngjykvfp@uO>esak{Ttd~q`7LRQ#P!Gej`#l-czD!L#+_<;d4Gg zdiQUrW>`L)(`!L$1B7uT?FlIu`q(+I1zR>i_=&ng%TFNK(45+~HXOJqBZ{eA=qd5E zp%{vvbUTsWhwJJf6ut3MEyvUb2&Y)uPy-Stofd4>0Bb>ZR_p+;G8_!Fo;fn~T22~o z%$@J4trizkFKwu~{!wqVof6WUt9CcEffge3OAOVYTDeg1(uPAmI2@^djM`h(z^^vNYH7uGWg)UXY^qFY{CL=evcH`f5IB-~SlbI=ZPT>d@@l@0E;O zDrGU_#I3iFbc&@{U(J7hXx~$2B+EE_Gjd;XqLe(2omG)DB6?3Tw83?~72GJ>NfO0+H-(Gd{beYpb<2EoL0X&_6JYht zLP@WTH38PdrBfT+QZ}xN+g(F>F%qHClh;@O+}#!%omC@Bbg-?>MLm0R#|0009ILKmY** z5I_KdM5kLR|1Q0*~0R#|0009ILc!&Z#|9^dO zRQUG?PagOelYeEhmj709>KAiO@!uYOefpaVrG9lHV@H~02%(oV?a-wbjz?PY;Wwix(&EJe%CS z$lU=_G5W)SSk;~Fdm?d@nj-hv$Xwex!*(a#b+X

Uk{q{KeOE7^m{AGVD%ly>Fh^*LYR_ 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.45 --- When adding new functionality, think about the following: --- 1. Simplicity and ease of use over complexity, --- 2. Clear, concise and strict fields but allow for extensability, --- 3. User friendly over performance, but consider performance always. --- WARNING: This script should only be used while testing the schema and should --- not be applied to existing datasets since it drops all existing information. --- --- DESIGN NOTES --- * Every field from every pydantic model is represented as a native column. --- * No JSON columns are used. All arrays and nested objects are normalized --- into dedicated tables linked by foreign keys. --- * Physical quantities are stored as a REAL value + TEXT unit column pair. --- * Ordered arrays (phases, tap positions, matrix rows, curve points, etc.) --- include a position_index INTEGER to preserve ordering. --- * Polymorphic controller types use a type_discriminator TEXT column with a --- CHECK constraint listing the allowed subtypes. Subtype-specific fields are --- nullable and only populated for the relevant subtype. --- * Component tables mirror the Python pydantic model hierarchy: --- Topology : feeders -> substations -> buses --- Equipment : wire/cable catalogs -> branch/transformer/load equipment --- Components: loads, branches, transformers, DERs, switchgear --- ----------------------------------------------------------------------------- - --- ============================================================ --- DROP TABLES (most-dependent first) --- ============================================================ -DROP TABLE IF EXISTS time_series_associations; -DROP TABLE IF EXISTS regulator_winding_phases; -DROP TABLE IF EXISTS regulator_winding_buses; -DROP TABLE IF EXISTS regulator_controllers; -DROP TABLE IF EXISTS distribution_regulators; -DROP TABLE IF EXISTS transformer_winding_phases; -DROP TABLE IF EXISTS transformer_winding_buses; -DROP TABLE IF EXISTS distribution_transformers; -DROP TABLE IF EXISTS switch_phase_states; -DROP TABLE IF EXISTS matrix_impedance_switch_phases; -DROP TABLE IF EXISTS matrix_impedance_switches; -DROP TABLE IF EXISTS recloser_phase_states; -DROP TABLE IF EXISTS matrix_impedance_recloser_phases; -DROP TABLE IF EXISTS matrix_impedance_reclosers; -DROP TABLE IF EXISTS recloser_reclose_intervals; -DROP TABLE IF EXISTS recloser_controllers; -DROP TABLE IF EXISTS fuse_phase_states; -DROP TABLE IF EXISTS matrix_impedance_fuse_phases; -DROP TABLE IF EXISTS matrix_impedance_fuses; -DROP TABLE IF EXISTS geometry_branch_thermal_limits; -DROP TABLE IF EXISTS geometry_branch_phases; -DROP TABLE IF EXISTS geometry_branches; -DROP TABLE IF EXISTS sequence_impedance_branch_thermal_limits; -DROP TABLE IF EXISTS sequence_impedance_branch_phases; -DROP TABLE IF EXISTS sequence_impedance_branches; -DROP TABLE IF EXISTS matrix_impedance_branch_thermal_limits; -DROP TABLE IF EXISTS matrix_impedance_branch_phases; -DROP TABLE IF EXISTS matrix_impedance_branches; -DROP TABLE IF EXISTS distribution_voltage_source_phases; -DROP TABLE IF EXISTS distribution_voltage_sources; -DROP TABLE IF EXISTS distribution_capacitor_phases; -DROP TABLE IF EXISTS capacitor_controllers; -DROP TABLE IF EXISTS distribution_capacitors; -DROP TABLE IF EXISTS distribution_battery_phases; -DROP TABLE IF EXISTS distribution_batteries; -DROP TABLE IF EXISTS distribution_solar_phases; -DROP TABLE IF EXISTS distribution_solar; -DROP TABLE IF EXISTS distribution_load_phases; -DROP TABLE IF EXISTS distribution_loads; -DROP TABLE IF EXISTS inverter_controllers; -DROP TABLE IF EXISTS inverter_active_power_controls; -DROP TABLE IF EXISTS inverter_reactive_power_controls; -DROP TABLE IF EXISTS bus_voltage_limits; -DROP TABLE IF EXISTS bus_phases; -DROP TABLE IF EXISTS distribution_buses; -DROP TABLE IF EXISTS substation_feeders; -DROP TABLE IF EXISTS distribution_substations; -DROP TABLE IF EXISTS distribution_feeders; -DROP TABLE IF EXISTS thermal_limit_sets; -DROP TABLE IF EXISTS voltage_limit_sets; -DROP TABLE IF EXISTS voltage_source_phases; -DROP TABLE IF EXISTS voltage_source_equipment; -DROP TABLE IF EXISTS phase_voltage_source_equipment; -DROP TABLE IF EXISTS inverter_equipment; -DROP TABLE IF EXISTS battery_equipment; -DROP TABLE IF EXISTS solar_equipment; -DROP TABLE IF EXISTS capacitor_equipment_phases; -DROP TABLE IF EXISTS capacitor_equipment; -DROP TABLE IF EXISTS phase_capacitor_equipment; -DROP TABLE IF EXISTS load_equipment_phases; -DROP TABLE IF EXISTS load_equipment; -DROP TABLE IF EXISTS phase_load_equipment; -DROP TABLE IF EXISTS winding_tap_positions; -DROP TABLE IF EXISTS transformer_coupling_sequences; -DROP TABLE IF EXISTS winding_equipment; -DROP TABLE IF EXISTS distribution_transformer_equipment; -DROP TABLE IF EXISTS impedance_matrix_entries; -DROP TABLE IF EXISTS matrix_impedance_switch_equipment; -DROP TABLE IF EXISTS switch_controllers; -DROP TABLE IF EXISTS recloser_controller_equipment; -DROP TABLE IF EXISTS matrix_impedance_recloser_equipment; -DROP TABLE IF EXISTS matrix_impedance_fuse_equipment; -DROP TABLE IF EXISTS matrix_impedance_branch_equipment; -DROP TABLE IF EXISTS sequence_impedance_branch_equipment; -DROP TABLE IF EXISTS geometry_branch_conductors; -DROP TABLE IF EXISTS geometry_branch_equipment; -DROP TABLE IF EXISTS concentric_cable_equipment; -DROP TABLE IF EXISTS bare_conductor_equipment; -DROP TABLE IF EXISTS time_current_curve_points; -DROP TABLE IF EXISTS time_current_curves; -DROP TABLE IF EXISTS curve_points; -DROP TABLE IF EXISTS curves; -DROP TABLE IF EXISTS wire_insulation_types; -DROP TABLE IF EXISTS line_types; -DROP TABLE IF EXISTS transformer_mountings; -DROP TABLE IF EXISTS connection_types; -DROP TABLE IF EXISTS voltage_types; -DROP TABLE IF EXISTS limit_types; -DROP TABLE IF EXISTS phases; - -PRAGMA foreign_keys = ON; - --- ============================================================ --- REFERENCE / ENUM TABLES --- ============================================================ - -CREATE TABLE phases (name TEXT PRIMARY KEY); -INSERT INTO phases VALUES ('A'), ('B'), ('C'), ('N'), ('S1'), ('S2'); - -CREATE TABLE voltage_types (name TEXT PRIMARY KEY); -INSERT INTO voltage_types VALUES ('line-to-line'), ('line-to-ground'); - -CREATE TABLE connection_types (name TEXT PRIMARY KEY); -INSERT INTO connection_types VALUES - ('STAR'), ('DELTA'), ('OPEN_DELTA'), ('OPEN_STAR'), ('ZIG_ZAG'); - -CREATE TABLE limit_types (name TEXT PRIMARY KEY); -INSERT INTO limit_types VALUES ('min'), ('max'); - -CREATE TABLE transformer_mountings (name TEXT PRIMARY KEY); -INSERT INTO transformer_mountings VALUES - ('POLE_MOUNT'), ('PAD_MOUNT'), ('UNDERGROUND_VAULT'); - -CREATE TABLE line_types (name TEXT PRIMARY KEY); -INSERT INTO line_types VALUES ('OVERHEAD'), ('UNDERGROUND'); - --- Relative permittivity values for wire insulation materials. -CREATE TABLE wire_insulation_types ( - name TEXT PRIMARY KEY, - dielectric REAL NOT NULL -); -INSERT INTO wire_insulation_types VALUES - ('AIR', 1.0), ('PVC', 3.18), ('XLPE', 2.3), ('EPR', 2.5), - ('PE', 2.25), ('TEFLON', 2.1), ('SILICONE_RUBBER', 3.5), - ('PAPER', 3.7), ('MICA', 6.0); - --- ============================================================ --- CURVE TABLES --- ============================================================ - --- Generic (x, y) curve -- used for volt-var, volt-watt, PV power-temp, --- and inverter efficiency curves. -CREATE TABLE curves ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '' -); - --- Ordered breakpoints for a Curve. -CREATE TABLE curve_points ( - id INTEGER PRIMARY KEY, - curve_id INTEGER NOT NULL REFERENCES curves (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - x_value REAL NOT NULL, - y_value REAL NOT NULL, - UNIQUE (curve_id, position_index) -); - --- Time-current curve header -- used for fuse and recloser TCC protection curves. -CREATE TABLE time_current_curves ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '' -); - --- Ordered breakpoints for a TimeCurrentCurve. -CREATE TABLE time_current_curve_points ( - id INTEGER PRIMARY KEY, - curve_id INTEGER NOT NULL REFERENCES time_current_curves (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - current_value REAL NOT NULL CHECK (current_value >= 0), - current_unit TEXT NOT NULL DEFAULT 'ampere', - time_value REAL NOT NULL CHECK (time_value >= 0), - time_unit TEXT NOT NULL DEFAULT 'second', - UNIQUE (curve_id, position_index) -); - --- ============================================================ --- WIRE / CABLE CATALOG --- ============================================================ - --- Bare conductor (overhead wire) catalog entry. -CREATE TABLE bare_conductor_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - conductor_diameter REAL NOT NULL CHECK (conductor_diameter > 0), - conductor_diameter_unit TEXT NOT NULL DEFAULT 'meter', - conductor_gmr REAL NOT NULL CHECK (conductor_gmr > 0), - conductor_gmr_unit TEXT NOT NULL DEFAULT 'meter', - ampacity REAL NOT NULL CHECK (ampacity > 0), - ampacity_unit TEXT NOT NULL DEFAULT 'ampere', - emergency_ampacity REAL NOT NULL CHECK (emergency_ampacity > 0), - emergency_ampacity_unit TEXT NOT NULL DEFAULT 'ampere', - ac_resistance REAL NOT NULL CHECK (ac_resistance > 0), - ac_resistance_unit TEXT NOT NULL DEFAULT 'ohm/meter', - dc_resistance REAL NOT NULL CHECK (dc_resistance > 0), - dc_resistance_unit TEXT NOT NULL DEFAULT 'ohm/meter' -); - --- Concentric (underground) cable catalog entry. -CREATE TABLE concentric_cable_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - strand_diameter REAL NOT NULL CHECK (strand_diameter > 0), - strand_diameter_unit TEXT NOT NULL DEFAULT 'meter', - conductor_diameter REAL NOT NULL CHECK (conductor_diameter > 0), - conductor_diameter_unit TEXT NOT NULL DEFAULT 'meter', - cable_diameter REAL NOT NULL CHECK (cable_diameter > 0), - cable_diameter_unit TEXT NOT NULL DEFAULT 'meter', - insulation_thickness REAL NOT NULL CHECK (insulation_thickness > 0), - insulation_thickness_unit TEXT NOT NULL DEFAULT 'meter', - insulation_diameter REAL NOT NULL CHECK (insulation_diameter > 0), - insulation_diameter_unit TEXT NOT NULL DEFAULT 'meter', - ampacity REAL NOT NULL CHECK (ampacity > 0), - ampacity_unit TEXT NOT NULL DEFAULT 'ampere', - conductor_gmr REAL NOT NULL CHECK (conductor_gmr > 0), - conductor_gmr_unit TEXT NOT NULL DEFAULT 'meter', - strand_gmr REAL NOT NULL CHECK (strand_gmr > 0), - strand_gmr_unit TEXT NOT NULL DEFAULT 'meter', - phase_ac_resistance REAL NOT NULL CHECK (phase_ac_resistance > 0), - phase_ac_resistance_unit TEXT NOT NULL DEFAULT 'ohm/meter', - strand_ac_resistance REAL NOT NULL CHECK (strand_ac_resistance > 0), - strand_ac_resistance_unit TEXT NOT NULL DEFAULT 'ohm/meter', - num_neutral_strands INTEGER NOT NULL CHECK (num_neutral_strands > 0), - rated_voltage REAL NOT NULL CHECK (rated_voltage > 0), - rated_voltage_unit TEXT NOT NULL DEFAULT 'volt', - insulation TEXT NOT NULL DEFAULT 'PE' - REFERENCES wire_insulation_types (name) -); - --- ============================================================ --- BRANCH EQUIPMENT --- ============================================================ - --- Sequence impedance branch equipment. -CREATE TABLE sequence_impedance_branch_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - pos_seq_resistance REAL NOT NULL, - pos_seq_resistance_unit TEXT NOT NULL DEFAULT 'ohm/meter', - zero_seq_resistance REAL NOT NULL, - zero_seq_resistance_unit TEXT NOT NULL DEFAULT 'ohm/meter', - pos_seq_reactance REAL NOT NULL, - pos_seq_reactance_unit TEXT NOT NULL DEFAULT 'ohm/meter', - zero_seq_reactance REAL NOT NULL, - zero_seq_reactance_unit TEXT NOT NULL DEFAULT 'ohm/meter', - pos_seq_capacitance REAL NOT NULL, - pos_seq_capacitance_unit TEXT NOT NULL DEFAULT 'farad/meter', - zero_seq_capacitance REAL NOT NULL, - zero_seq_capacitance_unit TEXT NOT NULL DEFAULT 'farad/meter', - ampacity REAL NOT NULL CHECK (ampacity > 0), - ampacity_unit TEXT NOT NULL DEFAULT 'ampere' -); - --- Matrix impedance branch equipment header. --- The N*N R/X/C matrices are stored row-by-row in impedance_matrix_entries. -CREATE TABLE matrix_impedance_branch_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - construction TEXT NOT NULL DEFAULT 'OVERHEAD' REFERENCES line_types (name), - ampacity REAL NOT NULL CHECK (ampacity > 0), - ampacity_unit TEXT NOT NULL DEFAULT 'ampere' -); - --- Shared N*N impedance matrix storage for line, fuse, recloser, and switch equipment. --- equipment_type IN ('LINE','FUSE','RECLOSER','SWITCH') identifies the parent table. --- matrix_type IN ('R','X','C') identifies resistance, reactance, or capacitance. --- Cross-table FK enforcement is the responsibility of the application layer. -CREATE TABLE impedance_matrix_entries ( - id INTEGER PRIMARY KEY, - equipment_id INTEGER NOT NULL, - equipment_type TEXT NOT NULL CHECK (equipment_type IN ('LINE','FUSE','RECLOSER','SWITCH')), - matrix_type TEXT NOT NULL CHECK (matrix_type IN ('R','X','C')), - row_idx INTEGER NOT NULL CHECK (row_idx >= 0), - col_idx INTEGER NOT NULL CHECK (col_idx >= 0), - value REAL NOT NULL, - value_unit TEXT NOT NULL, - UNIQUE (equipment_id, equipment_type, matrix_type, row_idx, col_idx) -); - --- Fuse equipment: matrix impedance + TCC curve + trip delay. -CREATE TABLE matrix_impedance_fuse_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - construction TEXT NOT NULL DEFAULT 'OVERHEAD' REFERENCES line_types (name), - ampacity REAL NOT NULL CHECK (ampacity > 0), - ampacity_unit TEXT NOT NULL DEFAULT 'ampere', - delay REAL NOT NULL DEFAULT 0.0 CHECK (delay >= 0), - delay_unit TEXT NOT NULL DEFAULT 'second', - tcc_curve_id INTEGER NOT NULL REFERENCES time_current_curves (id) ON DELETE RESTRICT -); - --- Recloser controller equipment: physical relay model identified by name. -CREATE TABLE recloser_controller_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE -); - --- Recloser equipment: matrix impedance, protection logic is in recloser_controllers. -CREATE TABLE matrix_impedance_recloser_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - construction TEXT NOT NULL DEFAULT 'OVERHEAD' REFERENCES line_types (name), - ampacity REAL NOT NULL CHECK (ampacity > 0), - ampacity_unit TEXT NOT NULL DEFAULT 'ampere' -); - --- Switch controller: delay, normal state, and lock flag. -CREATE TABLE switch_controllers ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - delay REAL NOT NULL CHECK (delay >= 0), - delay_unit TEXT NOT NULL DEFAULT 'second', - normal_state TEXT NOT NULL CHECK (normal_state IN ('open', 'close')), - is_locked INTEGER NOT NULL DEFAULT 0 CHECK (is_locked IN (0, 1)) -); - --- Switch equipment: matrix impedance + optional switch controller. -CREATE TABLE matrix_impedance_switch_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - construction TEXT NOT NULL DEFAULT 'OVERHEAD' REFERENCES line_types (name), - ampacity REAL NOT NULL CHECK (ampacity > 0), - ampacity_unit TEXT NOT NULL DEFAULT 'ampere', - switch_controller_id INTEGER NULL - REFERENCES switch_controllers (id) ON DELETE SET NULL -); - --- Geometry branch equipment header. --- Conductor positions are stored in geometry_branch_conductors (one row per conductor). -CREATE TABLE geometry_branch_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - insulation TEXT NOT NULL DEFAULT 'AIR' REFERENCES wire_insulation_types (name) -); - --- Each row is one conductor slot in a geometry branch. --- Exactly one of bare_conductor_id / concentric_cable_id must be set. --- horizontal_position and vertical_position replace the former JSON position arrays. -CREATE TABLE geometry_branch_conductors ( - id INTEGER PRIMARY KEY, - equipment_id INTEGER NOT NULL - REFERENCES geometry_branch_equipment (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - horizontal_position REAL NOT NULL, - horizontal_position_unit TEXT NOT NULL DEFAULT 'meter', - vertical_position REAL NOT NULL, - vertical_position_unit TEXT NOT NULL DEFAULT 'meter', - bare_conductor_id INTEGER NULL - REFERENCES bare_conductor_equipment (id) ON DELETE SET NULL, - concentric_cable_id INTEGER NULL - REFERENCES concentric_cable_equipment (id) ON DELETE SET NULL, - CHECK ((bare_conductor_id IS NOT NULL) != (concentric_cable_id IS NOT NULL)), - UNIQUE (equipment_id, position_index) -); - --- ============================================================ --- TRANSFORMER EQUIPMENT --- ============================================================ - --- Distribution transformer / regulator equipment catalog header. -CREATE TABLE distribution_transformer_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - mounting TEXT NOT NULL DEFAULT 'POLE_MOUNT' - REFERENCES transformer_mountings (name), - pct_no_load_loss REAL NOT NULL - CHECK (pct_no_load_loss >= 0 AND pct_no_load_loss <= 100), - pct_full_load_loss REAL NOT NULL - CHECK (pct_full_load_loss >= 0 AND pct_full_load_loss <= 100), - is_center_tapped INTEGER NOT NULL CHECK (is_center_tapped IN (0, 1)) -); - --- Individual winding. Ordered tap_positions stored in winding_tap_positions. -CREATE TABLE winding_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - transformer_equipment_id INTEGER NOT NULL - REFERENCES distribution_transformer_equipment (id) ON DELETE CASCADE, - winding_index INTEGER NOT NULL CHECK (winding_index >= 0), - resistance REAL NOT NULL - CHECK (resistance >= 0 AND resistance <= 100), - is_grounded INTEGER NOT NULL CHECK (is_grounded IN (0, 1)), - rated_voltage REAL NOT NULL CHECK (rated_voltage > 0), - rated_voltage_unit TEXT NOT NULL DEFAULT 'volt', - voltage_type TEXT NOT NULL REFERENCES voltage_types (name), - rated_power REAL NOT NULL CHECK (rated_power > 0), - rated_power_unit TEXT NOT NULL DEFAULT 'volt_ampere', - num_phases INTEGER NOT NULL CHECK (num_phases >= 1 AND num_phases <= 3), - connection_type TEXT NOT NULL REFERENCES connection_types (name), - total_taps INTEGER NOT NULL DEFAULT 32, - min_tap_pu REAL NOT NULL DEFAULT 0.9 - CHECK (min_tap_pu >= 0 AND min_tap_pu <= 1.0), - max_tap_pu REAL NOT NULL DEFAULT 1.1 CHECK (max_tap_pu >= 1.0), - UNIQUE (transformer_equipment_id, winding_index) -); - --- Per-phase tap position for a winding (replaces tap_positions JSON array). -CREATE TABLE winding_tap_positions ( - id INTEGER PRIMARY KEY, - winding_id INTEGER NOT NULL REFERENCES winding_equipment (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - tap_value REAL NOT NULL, - UNIQUE (winding_id, position_index) -); - --- Winding-pair coupling record. --- Merges coupling_sequences and winding_reactances JSON arrays into one table. -CREATE TABLE transformer_coupling_sequences ( - id INTEGER PRIMARY KEY, - transformer_equipment_id INTEGER NOT NULL - REFERENCES distribution_transformer_equipment (id) ON DELETE CASCADE, - sequence_index INTEGER NOT NULL CHECK (sequence_index >= 0), - from_winding_index INTEGER NOT NULL CHECK (from_winding_index >= 0), - to_winding_index INTEGER NOT NULL CHECK (to_winding_index >= 0), - reactance REAL NOT NULL CHECK (reactance >= 0 AND reactance <= 100), - reactance_unit TEXT NOT NULL DEFAULT 'percent', - UNIQUE (transformer_equipment_id, sequence_index) -); - --- ============================================================ --- LOAD EQUIPMENT --- ============================================================ - --- Single-phase load (ZIP model). -CREATE TABLE phase_load_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - real_power REAL NOT NULL DEFAULT 0.0 CHECK (real_power >= 0), - real_power_unit TEXT NOT NULL DEFAULT 'kilowatt', - reactive_power REAL NOT NULL DEFAULT 0.0, - reactive_power_unit TEXT NOT NULL DEFAULT 'kilovar', - z_real REAL NOT NULL, - z_imag REAL NOT NULL, - i_real REAL NOT NULL, - i_imag REAL NOT NULL, - p_real REAL NOT NULL, - p_imag REAL NOT NULL, - num_customers INTEGER NULL CHECK (num_customers > 0) -); - --- Multi-phase load equipment header. -CREATE TABLE load_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - connection_type TEXT NOT NULL DEFAULT 'STAR' REFERENCES connection_types (name) -); - --- Ordered per-phase load list (replaces phase_load_ids JSON array). -CREATE TABLE load_equipment_phases ( - id INTEGER PRIMARY KEY, - load_equipment_id INTEGER NOT NULL REFERENCES load_equipment (id) ON DELETE CASCADE, - phase_load_equipment_id INTEGER NOT NULL REFERENCES phase_load_equipment (id) ON DELETE RESTRICT, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (load_equipment_id, position_index) -); - --- ============================================================ --- CAPACITOR EQUIPMENT --- ============================================================ - --- Single-phase capacitor bank. -CREATE TABLE phase_capacitor_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - resistance REAL NOT NULL DEFAULT 0.0 CHECK (resistance >= 0), - resistance_unit TEXT NOT NULL DEFAULT 'ohm', - reactance REAL NOT NULL DEFAULT 0.0 CHECK (reactance >= 0), - reactance_unit TEXT NOT NULL DEFAULT 'ohm', - rated_reactive_power REAL NOT NULL CHECK (rated_reactive_power > 0), - rated_reactive_power_unit TEXT NOT NULL DEFAULT 'var', - num_banks_on INTEGER NOT NULL CHECK (num_banks_on >= 0), - num_banks INTEGER NOT NULL DEFAULT 1 CHECK (num_banks > 0) -); - --- Multi-phase capacitor equipment header. -CREATE TABLE capacitor_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - connection_type TEXT NOT NULL DEFAULT 'STAR' REFERENCES connection_types (name), - rated_voltage REAL NOT NULL CHECK (rated_voltage > 0), - rated_voltage_unit TEXT NOT NULL DEFAULT 'volt', - voltage_type TEXT NOT NULL REFERENCES voltage_types (name) -); - --- Ordered per-phase capacitor list (replaces phase_capacitor_ids JSON array). -CREATE TABLE capacitor_equipment_phases ( - id INTEGER PRIMARY KEY, - capacitor_equipment_id INTEGER NOT NULL - REFERENCES capacitor_equipment (id) ON DELETE CASCADE, - phase_capacitor_equipment_id INTEGER NOT NULL - REFERENCES phase_capacitor_equipment (id) ON DELETE RESTRICT, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (capacitor_equipment_id, position_index) -); - --- ============================================================ --- SOLAR / BATTERY / INVERTER EQUIPMENT --- ============================================================ - --- PV array equipment. --- power_temp_curve_id replaces the former power_temp_curve JSON column. -CREATE TABLE solar_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - rated_power REAL NOT NULL CHECK (rated_power > 0), - rated_power_unit TEXT NOT NULL DEFAULT 'kilowatt', - power_temp_curve_id INTEGER NULL REFERENCES curves (id) ON DELETE SET NULL, - resistance REAL NOT NULL CHECK (resistance >= 0 AND resistance <= 100), - reactance REAL NOT NULL CHECK (reactance >= 0 AND reactance <= 100), - rated_voltage REAL NOT NULL CHECK (rated_voltage > 0), - rated_voltage_unit TEXT NOT NULL DEFAULT 'volt', - voltage_type TEXT NOT NULL REFERENCES voltage_types (name) -); - --- Battery (DC) equipment. -CREATE TABLE battery_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - rated_energy REAL NOT NULL CHECK (rated_energy > 0), - rated_energy_unit TEXT NOT NULL DEFAULT 'kilowatt_hour', - rated_power REAL NOT NULL CHECK (rated_power >= 0), - rated_power_unit TEXT NOT NULL DEFAULT 'kilowatt', - charging_efficiency REAL NOT NULL - CHECK (charging_efficiency >= 0 AND charging_efficiency <= 100), - discharging_efficiency REAL NOT NULL - CHECK (discharging_efficiency >= 0 AND discharging_efficiency <= 100), - idling_efficiency REAL NOT NULL - CHECK (idling_efficiency >= 0 AND idling_efficiency <= 100), - rated_voltage REAL NOT NULL CHECK (rated_voltage >= 0), - rated_voltage_unit TEXT NOT NULL DEFAULT 'volt', - voltage_type TEXT NOT NULL REFERENCES voltage_types (name) -); - --- Inverter equipment. --- eff_curve_id replaces the former eff_curve JSON column. -CREATE TABLE inverter_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - rated_apparent_power REAL NOT NULL CHECK (rated_apparent_power > 0), - rated_apparent_power_unit TEXT NOT NULL DEFAULT 'volt_ampere', - rise_limit REAL NULL CHECK (rise_limit > 0), - rise_limit_unit TEXT NULL DEFAULT 'watt/second', - fall_limit REAL NULL CHECK (fall_limit > 0), - fall_limit_unit TEXT NULL DEFAULT 'watt/second', - cutout_percent REAL NOT NULL CHECK (cutout_percent >= 0 AND cutout_percent <= 100), - cutin_percent REAL NOT NULL CHECK (cutin_percent >= 0 AND cutin_percent <= 100), - dc_to_ac_efficiency REAL NOT NULL - CHECK (dc_to_ac_efficiency >= 0 AND dc_to_ac_efficiency <= 100), - eff_curve_id INTEGER NULL REFERENCES curves (id) ON DELETE SET NULL -); - --- ============================================================ --- VOLTAGE SOURCE EQUIPMENT --- ============================================================ - --- Single-phase Thevenin voltage source. -CREATE TABLE phase_voltage_source_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - r0 REAL NOT NULL, r0_unit TEXT NOT NULL DEFAULT 'ohm', - r1 REAL NOT NULL, r1_unit TEXT NOT NULL DEFAULT 'ohm', - x0 REAL NOT NULL, x0_unit TEXT NOT NULL DEFAULT 'ohm', - x1 REAL NOT NULL, x1_unit TEXT NOT NULL DEFAULT 'ohm', - voltage REAL NOT NULL CHECK (voltage > 0), - voltage_unit TEXT NOT NULL DEFAULT 'volt', - voltage_type TEXT NOT NULL DEFAULT 'line-to-line' REFERENCES voltage_types (name), - angle REAL NOT NULL, - angle_unit TEXT NOT NULL DEFAULT 'degree' -); - --- Three-phase voltage source header. -CREATE TABLE voltage_source_equipment ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE -); - --- Ordered list of per-phase sources (replaces source_ids JSON array). -CREATE TABLE voltage_source_phases ( - id INTEGER PRIMARY KEY, - voltage_source_equipment_id INTEGER NOT NULL - REFERENCES voltage_source_equipment (id) ON DELETE CASCADE, - phase_source_equipment_id INTEGER NOT NULL - REFERENCES phase_voltage_source_equipment (id) ON DELETE RESTRICT, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (voltage_source_equipment_id, position_index) -); - --- ============================================================ --- LIMIT SETS --- ============================================================ - -CREATE TABLE voltage_limit_sets ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - limit_type TEXT NOT NULL REFERENCES limit_types (name), - value REAL NOT NULL CHECK (value > 0), - value_unit TEXT NOT NULL DEFAULT 'volt' -); - -CREATE TABLE thermal_limit_sets ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - limit_type TEXT NOT NULL REFERENCES limit_types (name), - value REAL NOT NULL CHECK (value > 0), - value_unit TEXT NOT NULL DEFAULT 'ampere' -); - --- ============================================================ --- TOPOLOGY --- ============================================================ - -CREATE TABLE distribution_feeders ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE -); - -CREATE TABLE distribution_substations ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE -); - --- Junction: feeders belonging to a substation. -CREATE TABLE substation_feeders ( - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - PRIMARY KEY (substation_id, feeder_id) -); - --- Bus: fundamental node of the distribution network. --- coordinate_x / coordinate_y replace the former coordinate JSON column. --- Phases are stored in bus_phases. -CREATE TABLE distribution_buses ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - substation_id INTEGER NOT NULL - REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL - REFERENCES distribution_feeders (id) ON DELETE CASCADE, - voltage_type TEXT NOT NULL REFERENCES voltage_types (name), - rated_voltage REAL NOT NULL CHECK (rated_voltage > 0), - rated_voltage_unit TEXT NOT NULL DEFAULT 'volt', - coordinate_x REAL NULL, - coordinate_y REAL NULL, - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); - --- Ordered phase list for a bus (replaces phases JSON array). -CREATE TABLE bus_phases ( - id INTEGER PRIMARY KEY, - bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (bus_id, position_index), - UNIQUE (bus_id, phase) -); - --- Voltage limit sets associated with a bus. -CREATE TABLE bus_voltage_limits ( - bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - limit_set_id INTEGER NOT NULL REFERENCES voltage_limit_sets (id) ON DELETE CASCADE, - PRIMARY KEY (bus_id, limit_set_id) -); - --- ============================================================ --- INVERTER CONTROLLER TABLES --- ============================================================ - --- Reactive power control setting for an inverter. --- controller_type discriminates between POWER_FACTOR and VOLT_VAR subtypes. -CREATE TABLE inverter_reactive_power_controls ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - controller_type TEXT NOT NULL CHECK (controller_type IN ('POWER_FACTOR', 'VOLT_VAR')), - supported_by TEXT NOT NULL - CHECK (supported_by IN ('battery-only','solar-only','battery-and-solar')), - -- POWER_FACTOR subtype: - power_factor REAL NULL CHECK (power_factor >= -1 AND power_factor <= 1), - -- VOLT_VAR subtype: - volt_var_curve_id INTEGER NULL REFERENCES curves (id) ON DELETE SET NULL, - var_follow INTEGER NULL CHECK (var_follow IN (0, 1)) -); - --- Active power control setting for an inverter. --- Subtypes: VOLT_WATT, PEAK_SHAVING, CAPACITY_FIRMING, TIME_BASED, --- SELF_CONSUMPTION, TIME_OF_USE, DEMAND_CHARGE. -CREATE TABLE inverter_active_power_controls ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - controller_type TEXT NOT NULL CHECK (controller_type IN ( - 'VOLT_WATT','PEAK_SHAVING','CAPACITY_FIRMING', - 'TIME_BASED','SELF_CONSUMPTION', - 'TIME_OF_USE','DEMAND_CHARGE')), - supported_by TEXT NOT NULL - CHECK (supported_by IN ('battery-only','solar-only','battery-and-solar')), - -- VOLT_WATT subtype: - volt_watt_curve_id INTEGER NULL REFERENCES curves (id) ON DELETE SET NULL, - -- PEAK_SHAVING subtype: - peak_shaving_target REAL NULL CHECK (peak_shaving_target >= 0), - peak_shaving_target_unit TEXT NULL DEFAULT 'watt', - base_loading_target REAL NULL CHECK (base_loading_target >= 0), - base_loading_target_unit TEXT NULL DEFAULT 'watt', - -- CAPACITY_FIRMING subtype: - max_active_power_roc REAL NULL, - max_active_power_roc_unit TEXT NULL DEFAULT 'watt/second', - min_active_power_roc REAL NULL, - min_active_power_roc_unit TEXT NULL DEFAULT 'watt/second', - -- TIME_BASED subtype (times stored as 'HH:MM:SS'): - charging_start_time TEXT NULL, - charging_end_time TEXT NULL, - discharging_start_time TEXT NULL, - discharging_end_time TEXT NULL, - charging_power REAL NULL CHECK (charging_power >= 0), - charging_power_unit TEXT NULL DEFAULT 'watt', - discharging_power REAL NULL CHECK (discharging_power >= 0), - discharging_power_unit TEXT NULL DEFAULT 'watt', - -- TIME_OF_USE / DEMAND_CHARGE subtype: - tariff_id INTEGER NULL, - CONSTRAINT check_volt_watt CHECK (controller_type != 'VOLT_WATT' OR volt_watt_curve_id IS NOT NULL), - CONSTRAINT check_peak_shave CHECK (controller_type != 'PEAK_SHAVING' OR - (peak_shaving_target IS NOT NULL AND base_loading_target IS NOT NULL)), - CONSTRAINT check_cap_firm CHECK (controller_type != 'CAPACITY_FIRMING' OR - (max_active_power_roc IS NOT NULL AND min_active_power_roc IS NOT NULL)), - CONSTRAINT check_time CHECK (controller_type != 'TIME_BASED' OR - (charging_start_time IS NOT NULL AND discharging_start_time IS NOT NULL)) -); - --- Top-level inverter controller (used by DistributionSolar and DistributionBattery). -CREATE TABLE inverter_controllers ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - prioritize_active_power INTEGER NOT NULL CHECK (prioritize_active_power IN (0, 1)), - night_mode INTEGER NOT NULL CHECK (night_mode IN (0, 1)), - active_power_control_id INTEGER NULL - REFERENCES inverter_active_power_controls (id) ON DELETE SET NULL, - reactive_power_control_id INTEGER NULL - REFERENCES inverter_reactive_power_controls (id) ON DELETE SET NULL -); - --- ============================================================ --- DISTRIBUTION COMPONENTS --- ============================================================ - --- DistributionLoad: ZIP load attached to a bus. -CREATE TABLE distribution_loads ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - load_equipment_id INTEGER NOT NULL REFERENCES load_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); - --- Ordered phase list for a DistributionLoad (replaces phases JSON array). -CREATE TABLE distribution_load_phases ( - id INTEGER PRIMARY KEY, - load_id INTEGER NOT NULL REFERENCES distribution_loads (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (load_id, position_index), - UNIQUE (load_id, phase) -); - --- DistributionSolar: PV system attached to a bus. --- inverter_controller_id replaces the former controller JSON column. -CREATE TABLE distribution_solar ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - irradiance REAL NOT NULL CHECK (irradiance >= 0), - irradiance_unit TEXT NOT NULL DEFAULT 'watt/meter^2', - active_power REAL NOT NULL CHECK (active_power >= 0), - active_power_unit TEXT NOT NULL DEFAULT 'watt', - reactive_power REAL NOT NULL, - reactive_power_unit TEXT NOT NULL DEFAULT 'watt', - solar_equipment_id INTEGER NOT NULL REFERENCES solar_equipment (id), - inverter_equipment_id INTEGER NOT NULL REFERENCES inverter_equipment (id), - inverter_controller_id INTEGER NULL - REFERENCES inverter_controllers (id) ON DELETE SET NULL, - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); - --- Ordered phase list for a DistributionSolar (replaces phases JSON array). -CREATE TABLE distribution_solar_phases ( - id INTEGER PRIMARY KEY, - solar_id INTEGER NOT NULL REFERENCES distribution_solar (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (solar_id, position_index), - UNIQUE (solar_id, phase) -); - --- DistributionBattery: battery energy storage attached to a bus. --- inverter_controller_id replaces the former controller JSON column. -CREATE TABLE distribution_batteries ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - active_power REAL NOT NULL, - active_power_unit TEXT NOT NULL DEFAULT 'watt', - reactive_power REAL NOT NULL, - reactive_power_unit TEXT NOT NULL DEFAULT 'watt', - battery_equipment_id INTEGER NOT NULL REFERENCES battery_equipment (id), - inverter_equipment_id INTEGER NOT NULL REFERENCES inverter_equipment (id), - inverter_controller_id INTEGER NULL - REFERENCES inverter_controllers (id) ON DELETE SET NULL, - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); - --- Ordered phase list for a DistributionBattery (replaces phases JSON array). -CREATE TABLE distribution_battery_phases ( - id INTEGER PRIMARY KEY, - battery_id INTEGER NOT NULL REFERENCES distribution_batteries (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (battery_id, position_index), - UNIQUE (battery_id, phase) -); - --- DistributionCapacitor: shunt capacitor bank attached to a bus. -CREATE TABLE distribution_capacitors ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - capacitor_equipment_id INTEGER NOT NULL REFERENCES capacitor_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); - --- Per-phase controller for a DistributionCapacitor (replaces controllers JSON array). --- controller_type discriminates the five CapacitorControllerBase subtypes. -CREATE TABLE capacitor_controllers ( - id INTEGER PRIMARY KEY, - capacitor_id INTEGER NOT NULL - REFERENCES distribution_capacitors (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - name TEXT NOT NULL DEFAULT '', - controller_type TEXT NOT NULL CHECK (controller_type IN ( - 'VOLTAGE','ACTIVE_POWER','REACTIVE_POWER','CURRENT','DAILY_TIMED')), - -- CapacitorControllerBase shared fields: - delay_on REAL NULL CHECK (delay_on >= 0), - delay_on_unit TEXT NULL DEFAULT 'second', - delay_off REAL NULL CHECK (delay_off >= 0), - delay_off_unit TEXT NULL DEFAULT 'second', - dead_time REAL NULL CHECK (dead_time >= 0), - dead_time_unit TEXT NULL DEFAULT 'second', - -- VOLTAGE subtype (VoltageCapacitorController): - on_voltage REAL NULL CHECK (on_voltage > 0), - on_voltage_unit TEXT NULL DEFAULT 'volt', - off_voltage REAL NULL CHECK (off_voltage > 0), - off_voltage_unit TEXT NULL DEFAULT 'volt', - pt_ratio REAL NULL CHECK (pt_ratio >= 0), - -- ACTIVE_POWER subtype (ActivePowerCapacitorController): - on_active_power REAL NULL CHECK (on_active_power >= 0), - on_active_power_unit TEXT NULL DEFAULT 'watt', - off_active_power REAL NULL CHECK (off_active_power > 0), - off_active_power_unit TEXT NULL DEFAULT 'watt', - -- REACTIVE_POWER subtype (ReactivePowerCapacitorController): - on_reactive_power REAL NULL CHECK (on_reactive_power > 0), - on_reactive_power_unit TEXT NULL DEFAULT 'var', - off_reactive_power REAL NULL CHECK (off_reactive_power > 0), - off_reactive_power_unit TEXT NULL DEFAULT 'var', - -- CURRENT subtype (CurrentCapacitorController): - on_current REAL NULL CHECK (on_current > 0), - on_current_unit TEXT NULL DEFAULT 'ampere', - off_current REAL NULL CHECK (off_current >= 0), - off_current_unit TEXT NULL DEFAULT 'ampere', - ct_ratio REAL NULL CHECK (ct_ratio >= 0), - -- DAILY_TIMED subtype (DailyTimedCapacitorController) -- stored as 'HH:MM:SS': - on_time TEXT NULL, - off_time TEXT NULL, - UNIQUE (capacitor_id, position_index) -); - --- Ordered phase list for a DistributionCapacitor (replaces phases JSON array). -CREATE TABLE distribution_capacitor_phases ( - id INTEGER PRIMARY KEY, - capacitor_id INTEGER NOT NULL REFERENCES distribution_capacitors (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (capacitor_id, position_index), - UNIQUE (capacitor_id, phase) -); - --- DistributionVoltageSource: Thevenin equivalent voltage source at a bus. -CREATE TABLE distribution_voltage_sources ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - bus_id INTEGER NOT NULL - REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL - REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL - REFERENCES distribution_feeders (id) ON DELETE CASCADE, - voltage_source_equipment_id INTEGER NOT NULL - REFERENCES voltage_source_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); - --- Ordered phase list for a DistributionVoltageSource (replaces phases JSON array). -CREATE TABLE distribution_voltage_source_phases ( - id INTEGER PRIMARY KEY, - vsource_id INTEGER NOT NULL REFERENCES distribution_voltage_sources (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (vsource_id, position_index), - UNIQUE (vsource_id, phase) -); - --- ============================================================ --- BRANCH COMPONENTS -- Lines --- ============================================================ --- from_bus_id / to_bus_id are the explicit FK columns; no buses JSON needed. - --- MatrixImpedanceBranch: full matrix line model. -CREATE TABLE matrix_impedance_branches ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - from_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - to_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - length REAL NOT NULL CHECK (length > 0), - length_unit TEXT NOT NULL DEFAULT 'meter', - equipment_id INTEGER NOT NULL REFERENCES matrix_impedance_branch_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); --- Ordered phase list for a MatrixImpedanceBranch (replaces phases JSON array). -CREATE TABLE matrix_impedance_branch_phases ( - id INTEGER PRIMARY KEY, - branch_id INTEGER NOT NULL REFERENCES matrix_impedance_branches (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (branch_id, position_index), - UNIQUE (branch_id, phase) -); --- Thermal limits junction (replaces thermal_limit_ids JSON array). -CREATE TABLE matrix_impedance_branch_thermal_limits ( - branch_id INTEGER NOT NULL - REFERENCES matrix_impedance_branches (id) ON DELETE CASCADE, - thermal_limit_set_id INTEGER NOT NULL - REFERENCES thermal_limit_sets (id) ON DELETE CASCADE, - PRIMARY KEY (branch_id, thermal_limit_set_id) -); - --- SequenceImpedanceBranch: positive/zero sequence line model. -CREATE TABLE sequence_impedance_branches ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - from_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - to_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - length REAL NOT NULL CHECK (length > 0), - length_unit TEXT NOT NULL DEFAULT 'meter', - equipment_id INTEGER NOT NULL REFERENCES sequence_impedance_branch_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); -CREATE TABLE sequence_impedance_branch_phases ( - id INTEGER PRIMARY KEY, - branch_id INTEGER NOT NULL REFERENCES sequence_impedance_branches (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (branch_id, position_index), - UNIQUE (branch_id, phase) -); -CREATE TABLE sequence_impedance_branch_thermal_limits ( - branch_id INTEGER NOT NULL - REFERENCES sequence_impedance_branches (id) ON DELETE CASCADE, - thermal_limit_set_id INTEGER NOT NULL - REFERENCES thermal_limit_sets (id) ON DELETE CASCADE, - PRIMARY KEY (branch_id, thermal_limit_set_id) -); - --- GeometryBranch: impedance computed from conductor geometry. -CREATE TABLE geometry_branches ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - from_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - to_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - length REAL NOT NULL CHECK (length > 0), - length_unit TEXT NOT NULL DEFAULT 'meter', - equipment_id INTEGER NOT NULL REFERENCES geometry_branch_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); -CREATE TABLE geometry_branch_phases ( - id INTEGER PRIMARY KEY, - branch_id INTEGER NOT NULL REFERENCES geometry_branches (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (branch_id, position_index), - UNIQUE (branch_id, phase) -); -CREATE TABLE geometry_branch_thermal_limits ( - branch_id INTEGER NOT NULL REFERENCES geometry_branches (id) ON DELETE CASCADE, - thermal_limit_set_id INTEGER NOT NULL REFERENCES thermal_limit_sets (id) ON DELETE CASCADE, - PRIMARY KEY (branch_id, thermal_limit_set_id) -); - --- ============================================================ --- BRANCH COMPONENTS -- Protective / Switching Devices --- ============================================================ - --- MatrixImpedanceFuse. -CREATE TABLE matrix_impedance_fuses ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - from_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - to_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - length REAL NOT NULL CHECK (length > 0), - length_unit TEXT NOT NULL DEFAULT 'meter', - equipment_id INTEGER NOT NULL REFERENCES matrix_impedance_fuse_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); --- Ordered phase list for a fuse (replaces phases JSON array). -CREATE TABLE matrix_impedance_fuse_phases ( - id INTEGER PRIMARY KEY, - fuse_id INTEGER NOT NULL REFERENCES matrix_impedance_fuses (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (fuse_id, position_index), - UNIQUE (fuse_id, phase) -); --- Per-phase closed/open state for a fuse (replaces is_closed JSON array). -CREATE TABLE fuse_phase_states ( - id INTEGER PRIMARY KEY, - fuse_id INTEGER NOT NULL REFERENCES matrix_impedance_fuses (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - phase TEXT NOT NULL REFERENCES phases (name), - is_closed INTEGER NOT NULL CHECK (is_closed IN (0, 1)), - UNIQUE (fuse_id, position_index) -); - --- Recloser controller tables. --- ground_delayed/fast, phase_delayed/fast reference time_current_curves. -CREATE TABLE recloser_controllers ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - delay REAL NOT NULL CHECK (delay >= 0), - delay_unit TEXT NOT NULL DEFAULT 'second', - ground_delayed_curve_id INTEGER NOT NULL - REFERENCES time_current_curves (id) ON DELETE RESTRICT, - ground_fast_curve_id INTEGER NOT NULL - REFERENCES time_current_curves (id) ON DELETE RESTRICT, - phase_delayed_curve_id INTEGER NOT NULL - REFERENCES time_current_curves (id) ON DELETE RESTRICT, - phase_fast_curve_id INTEGER NOT NULL - REFERENCES time_current_curves (id) ON DELETE RESTRICT, - num_fast_ops INTEGER NOT NULL CHECK (num_fast_ops >= 0), - num_shots INTEGER NOT NULL CHECK (num_shots >= 1), - reset_time REAL NOT NULL CHECK (reset_time >= 0), - reset_time_unit TEXT NOT NULL DEFAULT 'second', - equipment_id INTEGER NOT NULL - REFERENCES recloser_controller_equipment (id) ON DELETE RESTRICT -); --- Reclose intervals ordered array (replaces reclose_intervals Time[] array). -CREATE TABLE recloser_reclose_intervals ( - id INTEGER PRIMARY KEY, - recloser_controller_id INTEGER NOT NULL - REFERENCES recloser_controllers (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - interval_value REAL NOT NULL CHECK (interval_value >= 0), - interval_unit TEXT NOT NULL DEFAULT 'second', - UNIQUE (recloser_controller_id, position_index) -); - --- MatrixImpedanceRecloser. --- controller_id replaces the former controller JSON column. -CREATE TABLE matrix_impedance_reclosers ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - from_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - to_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - length REAL NOT NULL CHECK (length > 0), - length_unit TEXT NOT NULL DEFAULT 'meter', - equipment_id INTEGER NOT NULL REFERENCES matrix_impedance_recloser_equipment (id), - controller_id INTEGER NOT NULL REFERENCES recloser_controllers (id) ON DELETE RESTRICT, - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); --- Ordered phase list for a recloser (replaces phases JSON array). -CREATE TABLE matrix_impedance_recloser_phases ( - id INTEGER PRIMARY KEY, - recloser_id INTEGER NOT NULL REFERENCES matrix_impedance_reclosers (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (recloser_id, position_index), - UNIQUE (recloser_id, phase) -); --- Per-phase closed/open state for a recloser (replaces is_closed JSON array). -CREATE TABLE recloser_phase_states ( - id INTEGER PRIMARY KEY, - recloser_id INTEGER NOT NULL REFERENCES matrix_impedance_reclosers (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - phase TEXT NOT NULL REFERENCES phases (name), - is_closed INTEGER NOT NULL CHECK (is_closed IN (0, 1)), - UNIQUE (recloser_id, position_index) -); - --- MatrixImpedanceSwitch. -CREATE TABLE matrix_impedance_switches ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - from_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - to_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - substation_id INTEGER NOT NULL REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL REFERENCES distribution_feeders (id) ON DELETE CASCADE, - length REAL NOT NULL CHECK (length > 0), - length_unit TEXT NOT NULL DEFAULT 'meter', - equipment_id INTEGER NOT NULL REFERENCES matrix_impedance_switch_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); --- Ordered phase list for a switch (replaces phases JSON array). -CREATE TABLE matrix_impedance_switch_phases ( - id INTEGER PRIMARY KEY, - switch_id INTEGER NOT NULL REFERENCES matrix_impedance_switches (id) ON DELETE CASCADE, - phase TEXT NOT NULL REFERENCES phases (name), - position_index INTEGER NOT NULL CHECK (position_index >= 0), - UNIQUE (switch_id, position_index), - UNIQUE (switch_id, phase) -); --- Per-phase closed/open state for a switch (replaces is_closed JSON array). -CREATE TABLE switch_phase_states ( - id INTEGER PRIMARY KEY, - switch_id INTEGER NOT NULL REFERENCES matrix_impedance_switches (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - phase TEXT NOT NULL REFERENCES phases (name), - is_closed INTEGER NOT NULL CHECK (is_closed IN (0, 1)), - UNIQUE (switch_id, position_index) -); - --- ============================================================ --- TRANSFORMER / REGULATOR COMPONENTS --- ============================================================ - --- DistributionTransformer. --- bus_ids JSON replaced by transformer_winding_buses. --- winding_phases JSON replaced by transformer_winding_phases. -CREATE TABLE distribution_transformers ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - substation_id INTEGER NOT NULL - REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL - REFERENCES distribution_feeders (id) ON DELETE CASCADE, - equipment_id INTEGER NOT NULL - REFERENCES distribution_transformer_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); --- Ordered winding-to-bus mapping (replaces bus_ids JSON array). -CREATE TABLE transformer_winding_buses ( - id INTEGER PRIMARY KEY, - transformer_id INTEGER NOT NULL REFERENCES distribution_transformers (id) ON DELETE CASCADE, - winding_index INTEGER NOT NULL CHECK (winding_index >= 0), - bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - UNIQUE (transformer_id, winding_index) -); --- Ordered per-phase list for each winding (replaces winding_phases JSON array of arrays). -CREATE TABLE transformer_winding_phases ( - id INTEGER PRIMARY KEY, - transformer_id INTEGER NOT NULL REFERENCES distribution_transformers (id) ON DELETE CASCADE, - winding_index INTEGER NOT NULL CHECK (winding_index >= 0), - phase TEXT NOT NULL REFERENCES phases (name), - phase_index INTEGER NOT NULL CHECK (phase_index >= 0), - UNIQUE (transformer_id, winding_index, phase_index), - UNIQUE (transformer_id, winding_index, phase) -); - --- DistributionRegulator. --- bus_ids JSON replaced by regulator_winding_buses. --- winding_phases JSON replaced by regulator_winding_phases. --- controllers JSON replaced by regulator_controllers. -CREATE TABLE distribution_regulators ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - substation_id INTEGER NOT NULL - REFERENCES distribution_substations (id) ON DELETE CASCADE, - feeder_id INTEGER NOT NULL - REFERENCES distribution_feeders (id) ON DELETE CASCADE, - equipment_id INTEGER NOT NULL - REFERENCES distribution_transformer_equipment (id), - in_service INTEGER NOT NULL DEFAULT 1 CHECK (in_service IN (0, 1)) -); --- Ordered winding-to-bus mapping for a regulator. -CREATE TABLE regulator_winding_buses ( - id INTEGER PRIMARY KEY, - regulator_id INTEGER NOT NULL REFERENCES distribution_regulators (id) ON DELETE CASCADE, - winding_index INTEGER NOT NULL CHECK (winding_index >= 0), - bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE CASCADE, - UNIQUE (regulator_id, winding_index) -); --- Ordered per-phase list for each winding of a regulator. -CREATE TABLE regulator_winding_phases ( - id INTEGER PRIMARY KEY, - regulator_id INTEGER NOT NULL REFERENCES distribution_regulators (id) ON DELETE CASCADE, - winding_index INTEGER NOT NULL CHECK (winding_index >= 0), - phase TEXT NOT NULL REFERENCES phases (name), - phase_index INTEGER NOT NULL CHECK (phase_index >= 0), - UNIQUE (regulator_id, winding_index, phase_index), - UNIQUE (regulator_id, winding_index, phase) -); --- Per-phase regulator controller (replaces controllers JSON array). --- controlled_bus_id and controlled_phase replace the embedded DistributionBus object. -CREATE TABLE regulator_controllers ( - id INTEGER PRIMARY KEY, - regulator_id INTEGER NOT NULL REFERENCES distribution_regulators (id) ON DELETE CASCADE, - position_index INTEGER NOT NULL CHECK (position_index >= 0), - name TEXT NOT NULL DEFAULT '', - delay REAL NULL CHECK (delay >= 0), - delay_unit TEXT NULL DEFAULT 'second', - v_setpoint REAL NOT NULL CHECK (v_setpoint > 0), - v_setpoint_unit TEXT NOT NULL DEFAULT 'volt', - min_v_limit REAL NOT NULL CHECK (min_v_limit > 0), - min_v_limit_unit TEXT NOT NULL DEFAULT 'volt', - max_v_limit REAL NOT NULL CHECK (max_v_limit > 0), - max_v_limit_unit TEXT NOT NULL DEFAULT 'volt', - pt_ratio REAL NOT NULL CHECK (pt_ratio >= 0), - use_ldc INTEGER NOT NULL CHECK (use_ldc IN (0, 1)), - is_reversible INTEGER NOT NULL CHECK (is_reversible IN (0, 1)), - ldc_R REAL NULL CHECK (ldc_R >= 0), - ldc_R_unit TEXT NULL DEFAULT 'volt', - ldc_X REAL NULL CHECK (ldc_X >= 0), - ldc_X_unit TEXT NULL DEFAULT 'volt', - ct_primary REAL NULL CHECK (ct_primary >= 0), - ct_primary_unit TEXT NULL DEFAULT 'ampere', - max_step INTEGER NOT NULL CHECK (max_step >= 0), - bandwidth REAL NOT NULL CHECK (bandwidth >= 0), - bandwidth_unit TEXT NOT NULL DEFAULT 'volt', - controlled_bus_id INTEGER NOT NULL REFERENCES distribution_buses (id) ON DELETE RESTRICT, - controlled_phase TEXT NOT NULL REFERENCES phases (name), - UNIQUE (regulator_id, position_index) -); - --- ============================================================ --- TIME SERIES ASSOCIATIONS --- ============================================================ -CREATE TABLE time_series_associations ( - id INTEGER PRIMARY KEY, - time_series_uuid TEXT NOT NULL, - time_series_type TEXT NOT NULL, - initial_timestamp TEXT NOT NULL, - resolution TEXT NOT NULL, - horizon TEXT NULL, - "interval" TEXT NULL, - window_count INTEGER NULL, - length INTEGER NULL, - name TEXT NOT NULL, - owner_id INTEGER NOT NULL, - owner_type TEXT NOT NULL, - owner_category TEXT NOT NULL, - features TEXT NOT NULL, - scaling_factor_multiplier TEXT NULL, - metadata_uuid TEXT NOT NULL, - units TEXT NULL -); - -CREATE UNIQUE INDEX dist_ts_by_owner_name_res_feat - ON time_series_associations (owner_id, time_series_type, name, resolution, features); - -CREATE INDEX dist_ts_by_uuid - ON time_series_associations (time_series_uuid); diff --git a/schema.sql b/schema.sql deleted file mode 100644 index 43309750..00000000 --- a/schema.sql +++ /dev/null @@ -1,367 +0,0 @@ --- DISCLAIMER --- The current version of this schema only works for SQLITE >=3.45 --- When adding new functionality, think about the following: --- 1. Simplicity and ease of use over complexity, --- 2. Clear, consice and strict fields but allow for extensability, --- 3. User friendly over peformance, but consider performance always, --- WARNING: This script should only be used while testing the schema and should not --- be applied to existing dataset since it drops all the information it has. -DROP TABLE IF EXISTS thermal_generators; - -DROP TABLE IF EXISTS renewable_generators; - -DROP TABLE IF EXISTS hydro_generators; - -DROP TABLE IF EXISTS storage_units; - -DROP TABLE IF EXISTS prime_mover_types; - -DROP TABLE IF EXISTS balancing_topologies; - -DROP TABLE IF EXISTS supply_technologies; - -DROP TABLE IF EXISTS storage_technologies; - -DROP TABLE IF EXISTS transmission_lines; - -DROP TABLE IF EXISTS planning_regions; - -DROP TABLE IF EXISTS transmission_interchanges; - -DROP TABLE IF EXISTS entities; - -DROP TABLE IF EXISTS time_series_associations; - -DROP TABLE IF EXISTS attributes; - -DROP TABLE IF EXISTS loads; - -DROP TABLE IF EXISTS static_time_series; - -DROP TABLE IF EXISTS entity_types; - -DROP TABLE IF EXISTS supplemental_attributes; - -DROP TABLE IF EXISTS attributes_associations; - -DROP TABLE IF EXISTS arcs; - -DROP TABLE IF EXISTS hydro_reservoir; - -DROP TABLE IF EXISTS hydro_reservoir_connections; - -DROP TABLE IF EXISTS fuels; - -DROP TABLE IF EXISTS supplemental_attributes_association; - -DROP TABLE IF EXISTS transport_technologies; - -PRAGMA foreign_keys = ON; - --- NOTE: This table should not be interacted directly since it gets populated --- automatically. --- Table of certain entities of griddb schema. -CREATE TABLE entities ( - id integer PRIMARY KEY, - entity_table text NOT NULL, - entity_type text NOT NULL, - FOREIGN KEY (entity_type) REFERENCES entity_types (name) -); - --- Table of possible entity types -CREATE TABLE entity_types (name text PRIMARY KEY); - --- NOTE: Sienna-griddb follows the convention of the EIA prime mover where we --- have a `prime_mover` and `fuel` to classify generators/storage units. --- However, users could use any combination of `prime_mover` and `fuel` for --- their own application. The only constraint is that the uniqueness is enforced --- by the combination of (prime_mover, fuel) --- Categories to classify generating units and supply technologies -CREATE TABLE prime_mover_types ( - id integer PRIMARY KEY, - name text NOT NULL UNIQUE, - description text NULL -); - -CREATE TABLE fuels( - id integer PRIMARY KEY, - name text NOT NULL UNIQUE, - description text NULL -); - --- Investment regions -CREATE TABLE planning_regions ( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name text NOT NULL UNIQUE, - description text NULL -); - --- Balancing topologies for the system. Could be either buses, or larger --- aggregated regions. -CREATE TABLE balancing_topologies ( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name text NOT NULL UNIQUE, - area integer NULL REFERENCES planning_regions (id) ON DELETE SET NULL, - description text NULL -); - --- NOTE: The purpose of this table is to provide links different entities that --- naturally have a relantionship not model dependent (e.g., transmission lines, --- transmission interchanges, etc.). --- Physical connection between entities. -CREATE TABLE arcs ( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - from_id integer, - to_id integer, - FOREIGN KEY (from_id) REFERENCES entities (id) ON DELETE CASCADE, - FOREIGN KEY (to_id) REFERENCES entities (id) ON DELETE CASCADE -); - --- Existing transmission lines -CREATE TABLE transmission_lines ( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name text NOT NULL UNIQUE, - arc_id integer, - continuous_rating real NULL CHECK (continuous_rating >= 0), - ste_rating real NULL CHECK (ste_rating >= 0), - lte_rating real NULL CHECK (lte_rating >= 0), - line_length real NULL CHECK (line_length >= 0), - FOREIGN KEY (arc_id) REFERENCES arcs (id) ON DELETE CASCADE -) strict; - --- NOTE: The purpose of this table is to provide physical limits to flows --- between areas or balancing topologies. In contrast with the transmission --- lines, this entities are used to enforce given physical limits of certain --- markets. --- Transmission interchanges between two balancing topologies or areas -CREATE TABLE transmission_interchanges ( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name text NOT NULL UNIQUE, - arc_id int REFERENCES arcs(id) ON DELETE CASCADE, - max_flow_from real NOT NULL, - max_flow_to real NOT NULL -) strict; - --- NOTE: The purpose of these tables is to capture data of **existing units only**. --- Table of thermal generation units (ThermalStandard, ThermalMultiStart) -CREATE TABLE thermal_generators ( - id INTEGER PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name TEXT NOT NULL UNIQUE, - prime_mover_type TEXT NOT NULL REFERENCES prime_mover_types(name), - fuel TEXT NOT NULL DEFAULT 'OTHER' REFERENCES fuels(name), - balancing_topology INTEGER NOT NULL REFERENCES balancing_topologies (id) ON DELETE CASCADE, - rating REAL NOT NULL CHECK (rating >= 0), - base_power REAL NOT NULL CHECK (base_power > 0), - -- Power limits (JSON: {"min": ..., "max": ...}): - active_power_limits JSON NOT NULL, - reactive_power_limits JSON NULL, - -- Ramp limits (JSON: {"up": ..., "down": ...}, MW/min): - ramp_limits JSON NULL, - -- Time limits (JSON: {"up": ..., "down": ...}, hours): - time_limits JSON NULL, - -- Operational flags: - must_run BOOLEAN NOT NULL DEFAULT FALSE, - available BOOLEAN NOT NULL DEFAULT TRUE, - STATUS BOOLEAN NOT NULL DEFAULT FALSE, - -- Initial setpoints: - active_power REAL NOT NULL DEFAULT 0.0, - reactive_power REAL NOT NULL DEFAULT 0.0, - -- Cost (complex structure, stored as JSON): - operation_cost JSON NOT NULL DEFAULT '{"cost_type": "THERMAL", "fixed": 0, "shut_down": 0, "start_up": 0, "variable": {"variable_cost_type": "COST", "power_units": "NATURAL_UNITS", "value_curve": {"curve_type": "INPUT_OUTPUT", "function_data": {"function_type": "LINEAR", "proportional_term": 0, "constant_term": 0}}, "vom_cost": {"curve_type": "INPUT_OUTPUT", "function_data": {"function_type": "LINEAR", "proportional_term": 0, "constant_term": 0}}}}' -); - --- Table of renewable generation units (RenewableDispatch, RenewableNonDispatch) -CREATE TABLE renewable_generators ( - id INTEGER PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name TEXT NOT NULL UNIQUE, - prime_mover_type TEXT NOT NULL REFERENCES prime_mover_types(name), - balancing_topology INTEGER NOT NULL REFERENCES balancing_topologies (id) ON DELETE CASCADE, - rating REAL NOT NULL CHECK (rating >= 0), - base_power REAL NOT NULL CHECK (base_power > 0), - -- Renewable-specific: - power_factor REAL NOT NULL DEFAULT 1.0 CHECK ( - power_factor > 0 - AND power_factor <= 1.0 - ), - -- Power limits (JSON: {"min": ..., "max": ...}): - reactive_power_limits JSON NULL, - -- Operational flags: - available BOOLEAN NOT NULL DEFAULT TRUE, - -- Initial setpoints: - active_power REAL NOT NULL DEFAULT 0.0, - reactive_power REAL NOT NULL DEFAULT 0.0, - -- Cost (NULL for RenewableNonDispatch): - operation_cost JSON NULL DEFAULT '{"cost_type":"RENEWABLE","fixed":0,"variable":{"variable_cost_type":"COST","power_units":"NATURAL_UNITS","value_curve":{"curve_type":"INPUT_OUTPUT","function_data":{"function_type":"LINEAR","proportional_term":0,"constant_term":0}},"vom_cost":{"curve_type":"INPUT_OUTPUT","function_data":{"function_type":"LINEAR","proportional_term":0,"constant_term":0}}},"curtailment_cost":{"variable_cost_type":"COST","power_units":"NATURAL_UNITS","value_curve":{"curve_type":"INPUT_OUTPUT","function_data":{"function_type":"LINEAR","proportional_term":0,"constant_term":0}},"vom_cost":{"curve_type":"INPUT_OUTPUT","function_data":{"function_type":"LINEAR","proportional_term":0,"constant_term":0}}}}' -); - --- Table of hydro generation units (HydroDispatch, HydroTurbine, HydroPumpTurbine) -CREATE TABLE hydro_generators ( - id INTEGER PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name TEXT NOT NULL UNIQUE, - prime_mover_type TEXT NOT NULL DEFAULT 'HY' REFERENCES prime_mover_types(name), - balancing_topology INTEGER NOT NULL REFERENCES balancing_topologies (id) ON DELETE CASCADE, - rating REAL NOT NULL CHECK (rating >= 0), - base_power REAL NOT NULL CHECK (base_power > 0), - -- Power limits (JSON: {"min": ..., "max": ...}): - active_power_limits JSON NOT NULL, - reactive_power_limits JSON NULL, - -- Ramp limits (JSON: {"up": ..., "down": ...}, MW/min): - ramp_limits JSON NULL, - -- Time limits (JSON: {"up": ..., "down": ...}, hours): - time_limits JSON NULL, - -- Operational flags: - available BOOLEAN NOT NULL DEFAULT TRUE, - -- Initial setpoints: - active_power REAL NOT NULL DEFAULT 0.0, - reactive_power REAL NOT NULL DEFAULT 0.0, - -- HydroTurbine/HydroPumpTurbine fields (nullable for HydroDispatch): - powerhouse_elevation REAL NULL DEFAULT 0.0 CHECK (powerhouse_elevation >= 0), - -- Outflow limits (JSON: {"min": ..., "max": ...}): - outflow_limits JSON NULL, - conversion_factor REAL NULL DEFAULT 1.0 CHECK (conversion_factor > 0), - travel_time REAL NULL CHECK (travel_time >= 0), - -- Cost: - operation_cost JSON NOT NULL DEFAULT '{"cost_type": "HYDRO_GEN", "fixed": 0.0, "variable": {"variable_cost_type": "COST", "power_units": "NATURAL_UNITS", "value_curve": {"curve_type": "INPUT_OUTPUT", "function_data": {"function_type": "LINEAR", "proportional_term": 0, "constant_term": 0}}, "vom_cost": {"curve_type": "INPUT_OUTPUT", "function_data": {"function_type": "LINEAR", "proportional_term": 0, "constant_term": 0}}}}' -- Note: efficiency (varies by type), turbine_type, and HydroPumpTurbine-specific - -- fields (active_power_limits_pump, etc.) are stored in the attributes table -); - --- NOTE: The purpose of this table is to capture data of **existing storage units only**. --- Table of energy storage units (including PHES or other kinds), -CREATE TABLE storage_units ( - id INTEGER PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name TEXT NOT NULL UNIQUE, - prime_mover_type TEXT NOT NULL REFERENCES prime_mover_types(name), - storage_technology_type TEXT NOT NULL, - balancing_topology INTEGER NOT NULL REFERENCES balancing_topologies (id) ON DELETE CASCADE, - rating REAL NOT NULL CHECK (rating >= 0), - base_power REAL NOT NULL CHECK (base_power > 0), - -- Storage capacity and limits (JSON: {"min": ..., "max": ...}): - storage_capacity REAL NOT NULL CHECK (storage_capacity >= 0), - storage_level_limits JSON NOT NULL, - initial_storage_capacity_level REAL NOT NULL CHECK (initial_storage_capacity_level >= 0), - -- Power limits (JSON: {"min": ..., "max": ...}, input = charging, output = discharging): - input_active_power_limits JSON NOT NULL, - output_active_power_limits JSON NOT NULL, - -- Efficiency (JSON: {"in": ..., "out": ...}): - efficiency JSON NOT NULL, - -- Reactive power (JSON: {"min": ..., "max": ...}): - reactive_power_limits JSON NULL, - -- Initial setpoints: - active_power REAL NOT NULL DEFAULT 0.0, - reactive_power REAL NOT NULL DEFAULT 0.0, - -- Status: - available BOOLEAN NOT NULL DEFAULT TRUE, - -- Storage-specific with defaults: - conversion_factor REAL NOT NULL DEFAULT 1.0 CHECK (conversion_factor > 0), - storage_target REAL NOT NULL DEFAULT 0.0, - cycle_limits INTEGER NOT NULL DEFAULT 10000 CHECK (cycle_limits > 0), - -- Cost: - operation_cost JSON NULL -); - --- Topological hydro reservoirs -CREATE TABLE hydro_reservoir(name text NOT NULL, UNIQUE(name)); - -CREATE TABLE hydro_reservoir_connections( - source_id integer NOT NULL REFERENCES entities(id) ON DELETE CASCADE, - sink_id integer NOT NULL REFERENCES entities(id) ON DELETE CASCADE, - CHECK (source_id <> sink_id), - PRIMARY KEY (source_id, sink_id) -); --- investment for expansion problems. --- Investment technology options for expansion problems -CREATE TABLE supply_technologies ( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - prime_mover_type text NOT NULL REFERENCES prime_mover_types(name), - fuel text NULL REFERENCES fuels(name), - area text NULL REFERENCES planning_regions (name) ON DELETE SET NULL, - balancing_topology text NULL REFERENCES balancing_topologies (name) ON DELETE SET NULL, - scenario text NULL, - UNIQUE(prime_mover_type, fuel, scenario) -); - -CREATE TABLE transport_technologies( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - arc_id integer NULL REFERENCES arcs(id) ON DELETE SET NULL, - scenario text NULL, - UNIQUE(id, arc_id, scenario) -); - --- NOTE: Attributes are additional parameters that can be linked to entities. --- The main purpose of this is when there is an important field that is not --- capture on the entity table that should exist on the model. Example of this --- fields are variable or fixed operation and maintenance cost or any other --- field that its representation is hard to fit into a `integer`, `real` or --- `text`. It must not be used for operational details since most of the should --- be included in the `operational_data` table. -CREATE TABLE attributes ( - id integer PRIMARY KEY, - entity_id integer NOT NULL, - TYPE text NOT NULL, - name text NOT NULL, - value json NOT NULL, - json_type text generated always AS (json_type(value)) virtual, - FOREIGN KEY (entity_id) REFERENCES entities (id) ON DELETE CASCADE -); - --- NOTE: Supplemental are optional parameters that can be linked to entities. --- The main purpose of this is to provide a way to save relevant information --- but that could or could not be used for modeling. not `text`. Examples of --- this field are geolocation (e.g., lat, long), outages, etc.) -CREATE TABLE supplemental_attributes ( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - TYPE text NOT NULL, - value json NOT NULL, - json_type text generated always AS (json_type (value)) virtual -); - -CREATE TABLE supplemental_attributes_association ( - attribute_id integer NOT NULL, - entity_id integer NOT NULL, - FOREIGN KEY (entity_id) REFERENCES entities (id) ON DELETE CASCADE, - FOREIGN KEY (attribute_id) REFERENCES supplemental_attributes (id) ON DELETE CASCADE -) strict; - -CREATE TABLE time_series_associations( - id INTEGER PRIMARY KEY, - time_series_uuid TEXT NOT NULL, - time_series_type TEXT NOT NULL, - initial_timestamp TEXT NOT NULL, - resolution TEXT NOT NULL, - horizon TEXT, - "interval" TEXT, - window_count INTEGER, - length INTEGER, - name TEXT NOT NULL, - owner_id INTEGER NOT NULL REFERENCES entities(id) ON DELETE CASCADE, - owner_type TEXT NOT NULL, - owner_category TEXT NOT NULL, - features TEXT NOT NULL, - scaling_factor_multiplier TEXT NULL, - metadata_uuid TEXT NOT NULL, - units TEXT NULL -); -CREATE UNIQUE INDEX "by_c_n_tst_features" ON "time_series_associations" ( - "owner_id", - "time_series_type", - "name", - "resolution", - "features" -); -CREATE INDEX "by_ts_uuid" ON "time_series_associations" ("time_series_uuid"); - - -CREATE TABLE loads ( - id integer PRIMARY KEY REFERENCES entities (id) ON DELETE CASCADE, - name TEXT NOT NULL UNIQUE, - balancing_topology INTEGER NOT NULL, - base_power DOUBLE, - FOREIGN KEY(balancing_topology) REFERENCES balancing_topologies (id) ON DELETE CASCADE -); - -CREATE TABLE static_time_series ( - id integer PRIMARY KEY, - uuid text NULL, - idx integer NOT NULL, - value real NOT NULL - \ No newline at end of file diff --git a/src/gdm/distribution/distribution_system.py b/src/gdm/distribution/distribution_system.py index 60d42dbe..6501da8e 100644 --- a/src/gdm/distribution/distribution_system.py +++ b/src/gdm/distribution/distribution_system.py @@ -220,8 +220,41 @@ def get_undirected_graph(self) -> nx.MultiGraph: edge.buses[1].name, **data, ) + + # Validate that every phase on each bus is served by at least one connected component. + self._warn_uncovered_bus_phases(edges) + return graph + def _warn_uncovered_bus_phases( + self, + edges: list, + ) -> None: + """Log a warning if any bus has phases not connected to any component.""" + bus_covered_phases: dict[str, set] = { + node.name: set() for node in self.get_components(DistributionBus) + } + for edge in edges: + if isinstance(edge, DistributionBranchBase): + edge_phase_set = set(edge.phases) + for bus in edge.buses: + bus_covered_phases[bus.name] |= edge_phase_set + elif isinstance(edge, DistributionTransformerBase): + for bus, winding_phases in zip(edge.buses, edge.winding_phases): + bus_covered_phases[bus.name] |= set(winding_phases) + + uncovered: dict[str, list] = {} + for bus in self.get_components(DistributionBus): + missing = set(bus.phases) - bus_covered_phases[bus.name] + if missing: + uncovered[bus.name] = sorted(p.value for p in missing) + + if uncovered: + details = "; ".join(f"{name}: {phases}" for name, phases in uncovered.items()) + logger.warning( + f"The following buses have phases not connected to any component: {details}" + ) + def _add_to_subsystem( self, subtree_system: "DistributionSystem",