pyconvexity 0.4.0__py3-none-any.whl → 0.4.1__py3-none-any.whl

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 (43) hide show
  1. pyconvexity/__init__.py +87 -46
  2. pyconvexity/_version.py +1 -1
  3. pyconvexity/core/__init__.py +3 -5
  4. pyconvexity/core/database.py +111 -103
  5. pyconvexity/core/errors.py +16 -10
  6. pyconvexity/core/types.py +61 -54
  7. pyconvexity/data/__init__.py +0 -1
  8. pyconvexity/data/loaders/cache.py +65 -64
  9. pyconvexity/data/schema/01_core_schema.sql +134 -234
  10. pyconvexity/data/schema/02_data_metadata.sql +38 -168
  11. pyconvexity/data/schema/03_validation_data.sql +327 -264
  12. pyconvexity/data/sources/gem.py +169 -139
  13. pyconvexity/io/__init__.py +4 -10
  14. pyconvexity/io/excel_exporter.py +694 -480
  15. pyconvexity/io/excel_importer.py +817 -545
  16. pyconvexity/io/netcdf_exporter.py +66 -61
  17. pyconvexity/io/netcdf_importer.py +850 -619
  18. pyconvexity/models/__init__.py +109 -59
  19. pyconvexity/models/attributes.py +197 -178
  20. pyconvexity/models/carriers.py +70 -67
  21. pyconvexity/models/components.py +260 -236
  22. pyconvexity/models/network.py +202 -284
  23. pyconvexity/models/results.py +65 -55
  24. pyconvexity/models/scenarios.py +58 -88
  25. pyconvexity/solvers/__init__.py +5 -5
  26. pyconvexity/solvers/pypsa/__init__.py +3 -3
  27. pyconvexity/solvers/pypsa/api.py +150 -134
  28. pyconvexity/solvers/pypsa/batch_loader.py +165 -162
  29. pyconvexity/solvers/pypsa/builder.py +390 -291
  30. pyconvexity/solvers/pypsa/constraints.py +184 -162
  31. pyconvexity/solvers/pypsa/solver.py +968 -663
  32. pyconvexity/solvers/pypsa/storage.py +1377 -671
  33. pyconvexity/timeseries.py +63 -60
  34. pyconvexity/validation/__init__.py +14 -6
  35. pyconvexity/validation/rules.py +95 -84
  36. pyconvexity-0.4.1.dist-info/METADATA +46 -0
  37. pyconvexity-0.4.1.dist-info/RECORD +42 -0
  38. pyconvexity/data/schema/04_scenario_schema.sql +0 -122
  39. pyconvexity/data/schema/migrate_add_geometries.sql +0 -73
  40. pyconvexity-0.4.0.dist-info/METADATA +0 -138
  41. pyconvexity-0.4.0.dist-info/RECORD +0 -44
  42. {pyconvexity-0.4.0.dist-info → pyconvexity-0.4.1.dist-info}/WHEEL +0 -0
  43. {pyconvexity-0.4.0.dist-info → pyconvexity-0.4.1.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,7 @@
1
1
  -- ============================================================================
2
- -- DATA STORAGE AND METADATA SCHEMA (OPTIMIZED)
3
- -- Essential tables for data storage and solve results only
4
- -- Removed unused audit logging and analysis caching for efficiency
5
- -- Version 2.2.0 - Optimized
2
+ -- DATA STORAGE AND METADATA SCHEMA
3
+ -- Essential tables for data storage and solve results
4
+ -- Version 3.1.0 - Simplified for single-network-per-file
6
5
  -- ============================================================================
7
6
 
8
7
  -- ============================================================================
@@ -10,76 +9,58 @@
10
9
  -- ============================================================================
11
10
 
12
11
  -- Generic data store for arbitrary network-level data
13
- -- Supports storing configuration, results, statistics, scripts, etc.
14
12
  CREATE TABLE network_data_store (
15
13
  id INTEGER PRIMARY KEY AUTOINCREMENT,
16
- network_id INTEGER NOT NULL,
17
14
  category TEXT NOT NULL, -- 'config', 'results', 'statistics', 'scripts', etc.
18
- name TEXT NOT NULL, -- Specific name within category
19
- data_format TEXT DEFAULT 'json', -- 'json', 'parquet', 'csv', 'binary', 'text'
20
- data BLOB NOT NULL, -- Serialized data
21
- metadata TEXT, -- JSON metadata about the data
22
- checksum TEXT, -- Data integrity hash
15
+ name TEXT NOT NULL,
16
+ data_format TEXT DEFAULT 'json', -- 'json', 'csv', 'binary', 'text'
17
+ data BLOB NOT NULL,
18
+ metadata TEXT, -- JSON metadata
19
+ checksum TEXT,
23
20
 
24
- -- Metadata
25
21
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
26
22
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
27
- created_by TEXT,
28
23
 
29
- CONSTRAINT fk_datastore_network
30
- FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE,
31
- CONSTRAINT uq_datastore_network_category_name
32
- UNIQUE (network_id, category, name),
24
+ CONSTRAINT uq_datastore_category_name
25
+ UNIQUE (category, name),
33
26
  CONSTRAINT valid_data_format
34
- CHECK (data_format IN ('json', 'parquet', 'csv', 'binary', 'text', 'yaml', 'toml'))
27
+ CHECK (data_format IN ('json', 'csv', 'binary', 'text', 'yaml', 'toml'))
35
28
  );
36
29
 
37
- -- Minimal indexes for data retrieval
38
- CREATE INDEX idx_datastore_network ON network_data_store(network_id);
39
- CREATE INDEX idx_datastore_category ON network_data_store(network_id, category);
30
+ CREATE INDEX idx_datastore_category ON network_data_store(category);
40
31
 
41
32
  -- ============================================================================
42
33
  -- DOCUMENTATION AND NOTES
43
34
  -- ============================================================================
44
35
 
45
- -- Network-level notes and documentation
36
+ -- Network-level notes
46
37
  CREATE TABLE network_notes (
47
38
  id INTEGER PRIMARY KEY AUTOINCREMENT,
48
- network_id INTEGER NOT NULL,
49
39
  title TEXT NOT NULL,
50
40
  content TEXT,
51
- tags TEXT, -- JSON array of tags
52
- note_type TEXT DEFAULT 'note', -- 'note', 'todo', 'warning', 'info'
53
- priority INTEGER DEFAULT 0, -- 0=normal, 1=high, -1=low
41
+ tags TEXT, -- JSON array
42
+ note_type TEXT DEFAULT 'note',
43
+ priority INTEGER DEFAULT 0,
54
44
 
55
- -- Metadata
56
45
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
57
46
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
58
- created_by TEXT,
59
47
 
60
- CONSTRAINT fk_notes_network
61
- FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE,
62
48
  CONSTRAINT valid_note_type
63
49
  CHECK (note_type IN ('note', 'todo', 'warning', 'info', 'doc'))
64
50
  );
65
51
 
66
- -- Minimal indexes for notes
67
- CREATE INDEX idx_notes_network ON network_notes(network_id);
68
-
69
- -- Component-specific notes and documentation
52
+ -- Component-specific notes
70
53
  CREATE TABLE component_notes (
71
54
  id INTEGER PRIMARY KEY AUTOINCREMENT,
72
55
  component_id INTEGER NOT NULL,
73
56
  title TEXT NOT NULL,
74
57
  content TEXT,
75
- tags TEXT, -- JSON array of tags
76
- note_type TEXT DEFAULT 'note', -- 'note', 'todo', 'warning', 'info'
77
- priority INTEGER DEFAULT 0, -- 0=normal, 1=high, -1=low
58
+ tags TEXT,
59
+ note_type TEXT DEFAULT 'note',
60
+ priority INTEGER DEFAULT 0,
78
61
 
79
- -- Metadata
80
62
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
81
63
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
82
- created_by TEXT,
83
64
 
84
65
  CONSTRAINT fk_component_notes_component
85
66
  FOREIGN KEY (component_id) REFERENCES components(id) ON DELETE CASCADE,
@@ -87,164 +68,53 @@ CREATE TABLE component_notes (
87
68
  CHECK (note_type IN ('note', 'todo', 'warning', 'info', 'doc'))
88
69
  );
89
70
 
90
- -- Minimal indexes for component notes
91
71
  CREATE INDEX idx_component_notes_component ON component_notes(component_id);
92
72
 
93
73
  -- ============================================================================
94
74
  -- SOLVE RESULTS AND STATISTICS
95
75
  -- ============================================================================
96
76
 
97
- -- Network solve results - stores solver outputs and statistics
98
- -- This is where PyPSA solve results are stored after successful solves
77
+ -- Network solve results - stores solver outputs per scenario
99
78
  CREATE TABLE network_solve_results (
100
- network_id INTEGER NOT NULL,
101
- scenario_id INTEGER NOT NULL, -- References scenarios table (master scenario has explicit ID)
79
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
80
+ scenario_id INTEGER, -- NULL for base network, non-NULL for scenario
102
81
 
103
82
  -- Solve metadata
104
83
  solved_at DATETIME DEFAULT CURRENT_TIMESTAMP,
105
- solver_name TEXT NOT NULL, -- 'highs', 'gurobi', 'cplex', etc.
106
- solve_type TEXT NOT NULL, -- 'pypsa_optimization', 'monte_carlo', 'sensitivity', etc.
107
- solve_status TEXT NOT NULL, -- 'optimal', 'infeasible', 'unbounded', etc.
108
- objective_value REAL, -- Objective function value
109
- solve_time_seconds REAL, -- Time taken to solve
84
+ solver_name TEXT NOT NULL,
85
+ solve_type TEXT NOT NULL,
86
+ solve_status TEXT NOT NULL,
87
+ objective_value REAL,
88
+ solve_time_seconds REAL,
110
89
 
111
- -- Everything else stored as JSON for maximum flexibility
112
- results_json TEXT NOT NULL, -- All results, statistics, whatever the solver produces
113
- metadata_json TEXT, -- Solver settings, input parameters, build info
90
+ -- Results stored as JSON
91
+ results_json TEXT NOT NULL,
92
+ metadata_json TEXT,
114
93
 
115
- PRIMARY KEY (network_id, scenario_id),
94
+ -- Only one result per scenario (including NULL for base network)
95
+ UNIQUE (scenario_id),
116
96
 
117
- FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE,
118
97
  FOREIGN KEY (scenario_id) REFERENCES scenarios(id) ON DELETE CASCADE
119
98
  );
120
99
 
121
- -- Minimal indexes for performance
122
- CREATE INDEX idx_solve_results_network ON network_solve_results(network_id);
123
100
  CREATE INDEX idx_solve_results_scenario ON network_solve_results(scenario_id);
124
101
 
125
- -- ============================================================================
126
- -- YEAR-BASED SOLVE RESULTS
127
- -- ============================================================================
128
-
129
- -- Year-based solve results - stores solver outputs and statistics by year
130
- -- This enables capacity expansion analysis and year-over-year comparisons
102
+ -- Year-based solve results for capacity expansion analysis
131
103
  CREATE TABLE network_solve_results_by_year (
132
104
  id INTEGER PRIMARY KEY AUTOINCREMENT,
133
- network_id INTEGER NOT NULL,
134
- scenario_id INTEGER NOT NULL,
105
+ scenario_id INTEGER, -- NULL for base network
135
106
  year INTEGER NOT NULL,
136
107
 
137
- -- Year-specific statistics (same structure as main results but year-specific)
138
- results_json TEXT NOT NULL, -- All results, statistics for this year only
139
- metadata_json TEXT, -- Solver settings, input parameters for this year
108
+ results_json TEXT NOT NULL,
109
+ metadata_json TEXT,
140
110
 
141
- -- Metadata
142
111
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
143
112
 
144
- CONSTRAINT fk_solve_results_year_network
145
- FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE,
146
113
  CONSTRAINT fk_solve_results_year_scenario
147
114
  FOREIGN KEY (scenario_id) REFERENCES scenarios(id) ON DELETE CASCADE,
148
115
  CONSTRAINT uq_solve_results_year_unique
149
- UNIQUE (network_id, scenario_id, year),
116
+ UNIQUE (scenario_id, year),
150
117
  CONSTRAINT valid_year CHECK (year >= 1900 AND year <= 2100)
151
118
  );
152
119
 
153
- -- Minimal indexes for performance
154
- CREATE INDEX idx_solve_results_year_network ON network_solve_results_by_year(network_id);
155
120
  CREATE INDEX idx_solve_results_year_scenario ON network_solve_results_by_year(scenario_id);
156
-
157
- -- Optional: Registry of solve type schemas for frontend introspection
158
- CREATE TABLE solve_type_schemas (
159
- solve_type TEXT PRIMARY KEY,
160
- schema_version TEXT NOT NULL,
161
- description TEXT,
162
- json_schema TEXT, -- JSON Schema describing the expected structure
163
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
164
- );
165
-
166
- -- ============================================================================
167
- -- UTILITY VIEWS (SIMPLIFIED)
168
- -- ============================================================================
169
-
170
- -- View for recent network activity (simplified without audit/cache tables)
171
- CREATE VIEW network_activity_summary AS
172
- SELECT
173
- n.id as network_id,
174
- n.name as network_name,
175
- COUNT(DISTINCT c.id) as components_count,
176
- COUNT(DISTINCT ca.id) as attributes_count,
177
- COUNT(DISTINCT nn.id) as notes_count,
178
- COUNT(DISTINCT nds.id) as data_store_entries_count,
179
- MAX(c.updated_at) as last_component_update,
180
- MAX(ca.updated_at) as last_attribute_update,
181
- MAX(nn.updated_at) as last_note_update,
182
- MAX(nds.updated_at) as last_data_update
183
- FROM networks n
184
- LEFT JOIN components c ON n.id = c.network_id
185
- LEFT JOIN component_attributes ca ON c.id = ca.component_id
186
- LEFT JOIN network_notes nn ON n.id = nn.network_id
187
- LEFT JOIN network_data_store nds ON n.id = nds.network_id
188
- GROUP BY n.id, n.name;
189
-
190
- -- ============================================================================
191
- -- CONNECTIVITY VIEWS - Human-readable bus connections
192
- -- ============================================================================
193
-
194
- -- View for components with single bus connections (generators, loads, etc.)
195
- CREATE VIEW components_with_bus AS
196
- SELECT
197
- c.*,
198
- b.name as bus_name
199
- FROM components c
200
- LEFT JOIN components b ON c.bus_id = b.id AND b.component_type = 'BUS'
201
- WHERE c.component_type IN ('GENERATOR', 'LOAD', 'STORAGE_UNIT', 'STORE');
202
-
203
- -- View for components with dual bus connections (lines, links)
204
- CREATE VIEW components_with_buses AS
205
- SELECT
206
- c.*,
207
- b0.name as bus0_name,
208
- b1.name as bus1_name
209
- FROM components c
210
- LEFT JOIN components b0 ON c.bus0_id = b0.id AND b0.component_type = 'BUS'
211
- LEFT JOIN components b1 ON c.bus1_id = b1.id AND b1.component_type = 'BUS'
212
- WHERE c.component_type IN ('LINE', 'LINK');
213
-
214
- -- Unified view for all components with resolved bus connections
215
- CREATE VIEW components_with_connectivity AS
216
- SELECT
217
- c.*,
218
- CASE
219
- WHEN c.component_type = 'BUS' THEN NULL
220
- WHEN c.component_type IN ('GENERATOR', 'LOAD', 'STORAGE_UNIT', 'STORE') THEN
221
- (SELECT b.name FROM components b WHERE b.id = c.bus_id AND b.component_type = 'BUS')
222
- ELSE NULL
223
- END as bus_name,
224
- CASE
225
- WHEN c.component_type IN ('LINE', 'LINK') THEN
226
- (SELECT b.name FROM components b WHERE b.id = c.bus0_id AND b.component_type = 'BUS')
227
- ELSE NULL
228
- END as bus0_name,
229
- CASE
230
- WHEN c.component_type IN ('LINE', 'LINK') THEN
231
- (SELECT b.name FROM components b WHERE b.id = c.bus1_id AND b.component_type = 'BUS')
232
- ELSE NULL
233
- END as bus1_name
234
- FROM components c;
235
-
236
- -- ============================================================================
237
- -- DEFAULT CARRIERS SETUP
238
- -- ============================================================================
239
-
240
- -- Note: Default carriers will be created automatically when a network is created
241
- -- This is handled in the application code to ensure proper network_id assignment
242
- -- The default carriers are:
243
- -- - AC (default for electrical buses and components)
244
- -- - DC (for DC electrical systems)
245
- -- - heat (for heating systems)
246
- -- - gas (for gas systems)
247
- -- - electricity (generic electrical carrier)
248
-
249
- -- These carriers follow PyPSA conventions and ensure all components can have
250
- -- appropriate carrier assignments without requiring manual setup