pyconvexity 0.1.0__py3-none-any.whl → 0.1.2__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.
- pyconvexity/_version.py +1 -1
- pyconvexity/core/database.py +20 -15
- pyconvexity/data/schema/01_core_schema.sql +426 -0
- pyconvexity/data/schema/02_data_metadata.sql +554 -0
- pyconvexity/data/schema/03_validation_data.sql +443 -0
- pyconvexity/data/schema/04_scenario_schema.sql +122 -0
- pyconvexity/models/attributes.py +3 -1
- {pyconvexity-0.1.0.dist-info → pyconvexity-0.1.2.dist-info}/METADATA +1 -1
- pyconvexity-0.1.2.dist-info/RECORD +20 -0
- pyconvexity-0.1.0.dist-info/RECORD +0 -16
- {pyconvexity-0.1.0.dist-info → pyconvexity-0.1.2.dist-info}/WHEEL +0 -0
- {pyconvexity-0.1.0.dist-info → pyconvexity-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- DATA STORAGE AND METADATA SCHEMA
|
|
3
|
+
-- Auxiliary tables for data storage, notes, audit logging, and analysis caching
|
|
4
|
+
-- Optimized for atomic operations and data management
|
|
5
|
+
-- Version 2.1.0
|
|
6
|
+
-- ============================================================================
|
|
7
|
+
|
|
8
|
+
-- ============================================================================
|
|
9
|
+
-- GENERIC DATA STORAGE
|
|
10
|
+
-- ============================================================================
|
|
11
|
+
|
|
12
|
+
-- Generic data store for arbitrary network-level data
|
|
13
|
+
-- Supports storing configuration, results, statistics, scripts, etc.
|
|
14
|
+
CREATE TABLE network_data_store (
|
|
15
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16
|
+
network_id INTEGER NOT NULL,
|
|
17
|
+
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
|
|
23
|
+
|
|
24
|
+
-- Metadata
|
|
25
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
26
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
27
|
+
created_by TEXT,
|
|
28
|
+
|
|
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),
|
|
33
|
+
CONSTRAINT valid_data_format
|
|
34
|
+
CHECK (data_format IN ('json', 'parquet', 'csv', 'binary', 'text', 'yaml', 'toml'))
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
-- Optimized 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);
|
|
40
|
+
CREATE INDEX idx_datastore_name ON network_data_store(network_id, category, name);
|
|
41
|
+
CREATE INDEX idx_datastore_created_at ON network_data_store(created_at);
|
|
42
|
+
CREATE INDEX idx_datastore_format ON network_data_store(data_format);
|
|
43
|
+
|
|
44
|
+
-- ============================================================================
|
|
45
|
+
-- DOCUMENTATION AND NOTES
|
|
46
|
+
-- ============================================================================
|
|
47
|
+
|
|
48
|
+
-- Network-level notes and documentation
|
|
49
|
+
CREATE TABLE network_notes (
|
|
50
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
51
|
+
network_id INTEGER NOT NULL,
|
|
52
|
+
title TEXT NOT NULL,
|
|
53
|
+
content TEXT,
|
|
54
|
+
tags TEXT, -- JSON array of tags
|
|
55
|
+
note_type TEXT DEFAULT 'note', -- 'note', 'todo', 'warning', 'info'
|
|
56
|
+
priority INTEGER DEFAULT 0, -- 0=normal, 1=high, -1=low
|
|
57
|
+
|
|
58
|
+
-- Metadata
|
|
59
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
60
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
61
|
+
created_by TEXT,
|
|
62
|
+
|
|
63
|
+
CONSTRAINT fk_notes_network
|
|
64
|
+
FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE,
|
|
65
|
+
CONSTRAINT valid_note_type
|
|
66
|
+
CHECK (note_type IN ('note', 'todo', 'warning', 'info', 'doc'))
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
CREATE INDEX idx_notes_network ON network_notes(network_id);
|
|
70
|
+
CREATE INDEX idx_notes_title ON network_notes(network_id, title);
|
|
71
|
+
CREATE INDEX idx_notes_type ON network_notes(note_type);
|
|
72
|
+
CREATE INDEX idx_notes_priority ON network_notes(priority);
|
|
73
|
+
CREATE INDEX idx_notes_created_at ON network_notes(created_at);
|
|
74
|
+
|
|
75
|
+
-- Component-specific notes and documentation
|
|
76
|
+
CREATE TABLE component_notes (
|
|
77
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
78
|
+
component_id INTEGER NOT NULL,
|
|
79
|
+
title TEXT NOT NULL,
|
|
80
|
+
content TEXT,
|
|
81
|
+
tags TEXT, -- JSON array of tags
|
|
82
|
+
note_type TEXT DEFAULT 'note', -- 'note', 'todo', 'warning', 'info'
|
|
83
|
+
priority INTEGER DEFAULT 0, -- 0=normal, 1=high, -1=low
|
|
84
|
+
|
|
85
|
+
-- Metadata
|
|
86
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
87
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
88
|
+
created_by TEXT,
|
|
89
|
+
|
|
90
|
+
CONSTRAINT fk_component_notes_component
|
|
91
|
+
FOREIGN KEY (component_id) REFERENCES components(id) ON DELETE CASCADE,
|
|
92
|
+
CONSTRAINT valid_component_note_type
|
|
93
|
+
CHECK (note_type IN ('note', 'todo', 'warning', 'info', 'doc'))
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
CREATE INDEX idx_component_notes_component ON component_notes(component_id);
|
|
97
|
+
CREATE INDEX idx_component_notes_title ON component_notes(component_id, title);
|
|
98
|
+
CREATE INDEX idx_component_notes_type ON component_notes(note_type);
|
|
99
|
+
CREATE INDEX idx_component_notes_priority ON component_notes(priority);
|
|
100
|
+
CREATE INDEX idx_component_notes_created_at ON component_notes(created_at);
|
|
101
|
+
|
|
102
|
+
-- ============================================================================
|
|
103
|
+
-- AUDIT AND CHANGE TRACKING
|
|
104
|
+
-- ============================================================================
|
|
105
|
+
|
|
106
|
+
-- Comprehensive audit log for tracking all database changes
|
|
107
|
+
CREATE TABLE audit_log (
|
|
108
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
109
|
+
network_id INTEGER,
|
|
110
|
+
table_name TEXT NOT NULL,
|
|
111
|
+
record_id INTEGER,
|
|
112
|
+
operation TEXT NOT NULL CHECK (operation IN ('INSERT', 'UPDATE', 'DELETE')),
|
|
113
|
+
|
|
114
|
+
-- Change data
|
|
115
|
+
old_values TEXT, -- JSON of old values for UPDATE/DELETE
|
|
116
|
+
new_values TEXT, -- JSON of new values for INSERT/UPDATE
|
|
117
|
+
change_summary TEXT, -- Human-readable summary of changes
|
|
118
|
+
affected_fields TEXT, -- JSON array of changed field names
|
|
119
|
+
|
|
120
|
+
-- Context and metadata
|
|
121
|
+
user_id TEXT,
|
|
122
|
+
session_id TEXT,
|
|
123
|
+
client_info TEXT, -- Application version, client type, etc.
|
|
124
|
+
transaction_id TEXT, -- For grouping related changes
|
|
125
|
+
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
126
|
+
|
|
127
|
+
-- Performance metrics
|
|
128
|
+
execution_time_ms INTEGER, -- Time taken for the operation
|
|
129
|
+
|
|
130
|
+
CONSTRAINT fk_audit_network
|
|
131
|
+
FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
-- Optimized indexes for audit queries
|
|
135
|
+
CREATE INDEX idx_audit_network ON audit_log(network_id);
|
|
136
|
+
CREATE INDEX idx_audit_table ON audit_log(table_name);
|
|
137
|
+
CREATE INDEX idx_audit_timestamp ON audit_log(timestamp);
|
|
138
|
+
CREATE INDEX idx_audit_operation ON audit_log(operation);
|
|
139
|
+
CREATE INDEX idx_audit_record ON audit_log(table_name, record_id);
|
|
140
|
+
CREATE INDEX idx_audit_user ON audit_log(user_id);
|
|
141
|
+
CREATE INDEX idx_audit_session ON audit_log(session_id);
|
|
142
|
+
CREATE INDEX idx_audit_transaction ON audit_log(transaction_id);
|
|
143
|
+
|
|
144
|
+
-- Change summary view for recent activity
|
|
145
|
+
CREATE VIEW recent_changes AS
|
|
146
|
+
SELECT
|
|
147
|
+
al.id,
|
|
148
|
+
al.network_id,
|
|
149
|
+
n.name as network_name,
|
|
150
|
+
al.table_name,
|
|
151
|
+
al.record_id,
|
|
152
|
+
al.operation,
|
|
153
|
+
al.change_summary,
|
|
154
|
+
al.user_id,
|
|
155
|
+
al.timestamp,
|
|
156
|
+
al.execution_time_ms
|
|
157
|
+
FROM audit_log al
|
|
158
|
+
LEFT JOIN networks n ON al.network_id = n.id
|
|
159
|
+
ORDER BY al.timestamp DESC
|
|
160
|
+
LIMIT 1000;
|
|
161
|
+
|
|
162
|
+
-- ============================================================================
|
|
163
|
+
-- NETWORK ANALYSIS AND RESULTS CACHING
|
|
164
|
+
-- ============================================================================
|
|
165
|
+
|
|
166
|
+
-- Cache for storing analysis results and computed data
|
|
167
|
+
-- This improves performance by avoiding recomputation of expensive operations
|
|
168
|
+
CREATE TABLE network_analysis_cache (
|
|
169
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
170
|
+
network_id INTEGER NOT NULL,
|
|
171
|
+
analysis_type TEXT NOT NULL, -- 'optimization', 'statistics', 'validation', 'powerflow', etc.
|
|
172
|
+
analysis_key TEXT NOT NULL, -- Unique key for this analysis (hash of inputs)
|
|
173
|
+
analysis_version TEXT, -- Version of analysis algorithm
|
|
174
|
+
|
|
175
|
+
-- Input tracking
|
|
176
|
+
input_hash TEXT, -- Hash of inputs that generated this result
|
|
177
|
+
input_summary TEXT, -- Human-readable summary of inputs
|
|
178
|
+
dependencies TEXT, -- JSON array of dependent data (components, attributes, etc.)
|
|
179
|
+
|
|
180
|
+
-- Results storage
|
|
181
|
+
result_data BLOB NOT NULL, -- Serialized results (typically JSON or Parquet)
|
|
182
|
+
result_format TEXT DEFAULT 'json', -- 'json', 'parquet', 'csv', 'binary'
|
|
183
|
+
result_summary TEXT, -- Human-readable summary of results
|
|
184
|
+
result_size_bytes INTEGER, -- Size of result data for management
|
|
185
|
+
|
|
186
|
+
-- Analysis metadata
|
|
187
|
+
analysis_time_ms INTEGER, -- Time taken for analysis
|
|
188
|
+
status TEXT DEFAULT 'completed', -- 'completed', 'failed', 'in_progress', 'stale'
|
|
189
|
+
error_message TEXT, -- If status is 'failed'
|
|
190
|
+
warnings TEXT, -- JSON array of warnings
|
|
191
|
+
|
|
192
|
+
-- Cache management
|
|
193
|
+
hit_count INTEGER DEFAULT 0, -- Number of times this cache entry was used
|
|
194
|
+
last_accessed DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
195
|
+
expires_at DATETIME, -- Optional expiration for cache cleanup
|
|
196
|
+
|
|
197
|
+
-- Metadata
|
|
198
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
199
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
200
|
+
created_by TEXT,
|
|
201
|
+
|
|
202
|
+
CONSTRAINT fk_analysis_cache_network
|
|
203
|
+
FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE,
|
|
204
|
+
CONSTRAINT uq_analysis_cache_key
|
|
205
|
+
UNIQUE (network_id, analysis_type, analysis_key),
|
|
206
|
+
CONSTRAINT valid_analysis_status
|
|
207
|
+
CHECK (status IN ('completed', 'failed', 'in_progress', 'stale')),
|
|
208
|
+
CONSTRAINT valid_result_format
|
|
209
|
+
CHECK (result_format IN ('json', 'parquet', 'csv', 'binary', 'text'))
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
-- Optimized indexes for cache operations
|
|
213
|
+
CREATE INDEX idx_analysis_cache_network ON network_analysis_cache(network_id);
|
|
214
|
+
CREATE INDEX idx_analysis_cache_type ON network_analysis_cache(network_id, analysis_type);
|
|
215
|
+
CREATE INDEX idx_analysis_cache_key ON network_analysis_cache(analysis_key);
|
|
216
|
+
CREATE INDEX idx_analysis_cache_status ON network_analysis_cache(status);
|
|
217
|
+
CREATE INDEX idx_analysis_cache_expires ON network_analysis_cache(expires_at);
|
|
218
|
+
CREATE INDEX idx_analysis_cache_accessed ON network_analysis_cache(last_accessed);
|
|
219
|
+
CREATE INDEX idx_analysis_cache_created ON network_analysis_cache(created_at);
|
|
220
|
+
CREATE INDEX idx_analysis_cache_size ON network_analysis_cache(result_size_bytes);
|
|
221
|
+
|
|
222
|
+
-- ============================================================================
|
|
223
|
+
-- SOLVE RESULTS AND STATISTICS
|
|
224
|
+
-- ============================================================================
|
|
225
|
+
|
|
226
|
+
-- Drop the old optimization_results table
|
|
227
|
+
DROP TABLE IF EXISTS optimization_results;
|
|
228
|
+
|
|
229
|
+
-- Network solve results - stores solver outputs and statistics
|
|
230
|
+
-- This is where PyPSA solve results are stored after successful solves
|
|
231
|
+
CREATE TABLE network_solve_results (
|
|
232
|
+
network_id INTEGER NOT NULL,
|
|
233
|
+
scenario_id INTEGER NOT NULL, -- References scenarios table (master scenario has explicit ID)
|
|
234
|
+
|
|
235
|
+
-- Solve metadata
|
|
236
|
+
solved_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
237
|
+
solver_name TEXT NOT NULL, -- 'highs', 'gurobi', 'cplex', etc.
|
|
238
|
+
solve_type TEXT NOT NULL, -- 'pypsa_optimization', 'monte_carlo', 'sensitivity', etc.
|
|
239
|
+
solve_status TEXT NOT NULL, -- 'optimal', 'infeasible', 'unbounded', etc.
|
|
240
|
+
objective_value REAL, -- Objective function value
|
|
241
|
+
solve_time_seconds REAL, -- Time taken to solve
|
|
242
|
+
|
|
243
|
+
-- Everything else stored as JSON for maximum flexibility
|
|
244
|
+
results_json TEXT NOT NULL, -- All results, statistics, whatever the solver produces
|
|
245
|
+
metadata_json TEXT, -- Solver settings, input parameters, build info
|
|
246
|
+
|
|
247
|
+
PRIMARY KEY (network_id, scenario_id),
|
|
248
|
+
|
|
249
|
+
FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE,
|
|
250
|
+
FOREIGN KEY (scenario_id) REFERENCES scenarios(id) ON DELETE CASCADE
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
-- Indexes for performance
|
|
254
|
+
CREATE INDEX idx_solve_results_network ON network_solve_results(network_id);
|
|
255
|
+
CREATE INDEX idx_solve_results_scenario ON network_solve_results(scenario_id);
|
|
256
|
+
CREATE INDEX idx_solve_results_status ON network_solve_results(solve_status);
|
|
257
|
+
CREATE INDEX idx_solve_results_solved_at ON network_solve_results(solved_at);
|
|
258
|
+
|
|
259
|
+
-- ============================================================================
|
|
260
|
+
-- YEAR-BASED SOLVE RESULTS
|
|
261
|
+
-- ============================================================================
|
|
262
|
+
|
|
263
|
+
-- Year-based solve results - stores solver outputs and statistics by year
|
|
264
|
+
-- This enables capacity expansion analysis and year-over-year comparisons
|
|
265
|
+
CREATE TABLE network_solve_results_by_year (
|
|
266
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
267
|
+
network_id INTEGER NOT NULL,
|
|
268
|
+
scenario_id INTEGER NOT NULL,
|
|
269
|
+
year INTEGER NOT NULL,
|
|
270
|
+
|
|
271
|
+
-- Year-specific statistics (same structure as main results but year-specific)
|
|
272
|
+
results_json TEXT NOT NULL, -- All results, statistics for this year only
|
|
273
|
+
metadata_json TEXT, -- Solver settings, input parameters for this year
|
|
274
|
+
|
|
275
|
+
-- Metadata
|
|
276
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
277
|
+
|
|
278
|
+
CONSTRAINT fk_solve_results_year_network
|
|
279
|
+
FOREIGN KEY (network_id) REFERENCES networks(id) ON DELETE CASCADE,
|
|
280
|
+
CONSTRAINT fk_solve_results_year_scenario
|
|
281
|
+
FOREIGN KEY (scenario_id) REFERENCES scenarios(id) ON DELETE CASCADE,
|
|
282
|
+
CONSTRAINT uq_solve_results_year_unique
|
|
283
|
+
UNIQUE (network_id, scenario_id, year),
|
|
284
|
+
CONSTRAINT valid_year CHECK (year >= 1900 AND year <= 2100)
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
-- Indexes for performance
|
|
288
|
+
CREATE INDEX idx_solve_results_year_network ON network_solve_results_by_year(network_id);
|
|
289
|
+
CREATE INDEX idx_solve_results_year_scenario ON network_solve_results_by_year(scenario_id);
|
|
290
|
+
CREATE INDEX idx_solve_results_year_year ON network_solve_results_by_year(year);
|
|
291
|
+
CREATE INDEX idx_solve_results_year_network_scenario ON network_solve_results_by_year(network_id, scenario_id);
|
|
292
|
+
CREATE INDEX idx_solve_results_year_created_at ON network_solve_results_by_year(created_at);
|
|
293
|
+
|
|
294
|
+
-- Optional: Registry of solve type schemas for frontend introspection
|
|
295
|
+
CREATE TABLE solve_type_schemas (
|
|
296
|
+
solve_type TEXT PRIMARY KEY,
|
|
297
|
+
schema_version TEXT NOT NULL,
|
|
298
|
+
description TEXT,
|
|
299
|
+
json_schema TEXT, -- JSON Schema describing the expected structure
|
|
300
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
/*
|
|
304
|
+
SUGGESTED JSON STRUCTURE FOR results_json:
|
|
305
|
+
|
|
306
|
+
For PyPSA optimization (solve_type = 'pypsa_optimization'):
|
|
307
|
+
{
|
|
308
|
+
"core_summary": {
|
|
309
|
+
"total_generation_mwh": 12500.0,
|
|
310
|
+
"total_demand_mwh": 12000.0,
|
|
311
|
+
"total_cost": 1500000.0,
|
|
312
|
+
"load_factor": 0.96,
|
|
313
|
+
"unserved_energy_mwh": 0.0
|
|
314
|
+
},
|
|
315
|
+
|
|
316
|
+
"pypsa_statistics": {
|
|
317
|
+
"energy_balance": {
|
|
318
|
+
"gas": 5000.0,
|
|
319
|
+
"wind": 7500.0,
|
|
320
|
+
"solar": 0.0
|
|
321
|
+
},
|
|
322
|
+
"supply_by_carrier": {
|
|
323
|
+
"gas": {"total_mwh": 5000.0, "capacity_factor": 0.85},
|
|
324
|
+
"wind": {"total_mwh": 7500.0, "capacity_factor": 0.42}
|
|
325
|
+
},
|
|
326
|
+
"demand_by_carrier": {
|
|
327
|
+
"electricity": 12000.0
|
|
328
|
+
},
|
|
329
|
+
"capacity_factors": {
|
|
330
|
+
"generator_gas_001": 0.85,
|
|
331
|
+
"generator_wind_001": 0.42
|
|
332
|
+
},
|
|
333
|
+
"curtailment": {
|
|
334
|
+
"wind": 250.0,
|
|
335
|
+
"solar": 0.0
|
|
336
|
+
},
|
|
337
|
+
"transmission_utilization": {
|
|
338
|
+
"line_001": 0.75,
|
|
339
|
+
"line_002": 0.32
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
"custom_statistics": {
|
|
344
|
+
"emissions_by_carrier": {
|
|
345
|
+
"gas": 2500.0,
|
|
346
|
+
"wind": 0.0,
|
|
347
|
+
"solar": 0.0
|
|
348
|
+
},
|
|
349
|
+
"total_emissions_tons_co2": 2500.0,
|
|
350
|
+
"average_price_per_mwh": 125.0,
|
|
351
|
+
"peak_demand_mw": 2500.0,
|
|
352
|
+
"renewable_fraction": 0.6
|
|
353
|
+
},
|
|
354
|
+
|
|
355
|
+
"runtime_info": {
|
|
356
|
+
"build_time_seconds": 5.2,
|
|
357
|
+
"solve_time_seconds": 45.1,
|
|
358
|
+
"result_processing_seconds": 2.3,
|
|
359
|
+
"component_count": 150,
|
|
360
|
+
"variable_count": 8760,
|
|
361
|
+
"constraint_count": 12500,
|
|
362
|
+
"memory_usage_mb": 256.5
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
"solver_info": {
|
|
366
|
+
"solver_name": "highs",
|
|
367
|
+
"solver_version": "1.6.0",
|
|
368
|
+
"solver_options": {"presolve": "on", "parallel": "on"},
|
|
369
|
+
"termination_condition": "optimal",
|
|
370
|
+
"iterations": 1247,
|
|
371
|
+
"barrier_iterations": null
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
For Monte Carlo sampling (solve_type = 'monte_carlo'):
|
|
376
|
+
{
|
|
377
|
+
"core_summary": {
|
|
378
|
+
"scenario_count": 1000,
|
|
379
|
+
"convergence_achieved": true,
|
|
380
|
+
"confidence_level": 0.95
|
|
381
|
+
},
|
|
382
|
+
|
|
383
|
+
"probability_distributions": {
|
|
384
|
+
"total_cost": {
|
|
385
|
+
"mean": 1500000.0,
|
|
386
|
+
"std": 150000.0,
|
|
387
|
+
"p05": 1250000.0,
|
|
388
|
+
"p50": 1500000.0,
|
|
389
|
+
"p95": 1750000.0
|
|
390
|
+
},
|
|
391
|
+
"unserved_energy": {
|
|
392
|
+
"mean": 12.5,
|
|
393
|
+
"std": 25.2,
|
|
394
|
+
"p05": 0.0,
|
|
395
|
+
"p50": 0.0,
|
|
396
|
+
"p95": 75.0
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
"sensitivity_analysis": {
|
|
401
|
+
"most_influential_parameters": [
|
|
402
|
+
{"parameter": "wind_capacity", "sensitivity": 0.85},
|
|
403
|
+
{"parameter": "fuel_price", "sensitivity": 0.72}
|
|
404
|
+
]
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
"runtime_info": {
|
|
408
|
+
"total_runtime_seconds": 3600.0,
|
|
409
|
+
"scenarios_per_second": 0.28
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
For sensitivity analysis (solve_type = 'sensitivity'):
|
|
414
|
+
{
|
|
415
|
+
"core_summary": {
|
|
416
|
+
"parameters_analyzed": 15,
|
|
417
|
+
"base_case_objective": 1500000.0
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
"parameter_sensitivities": {
|
|
421
|
+
"fuel_cost_gas": {
|
|
422
|
+
"sensitivity_coefficient": 0.85,
|
|
423
|
+
"objective_range": [1200000.0, 1800000.0],
|
|
424
|
+
"parameter_range": [50.0, 150.0]
|
|
425
|
+
},
|
|
426
|
+
"wind_capacity": {
|
|
427
|
+
"sensitivity_coefficient": -0.72,
|
|
428
|
+
"objective_range": [1300000.0, 1700000.0],
|
|
429
|
+
"parameter_range": [1000.0, 3000.0]
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
|
|
433
|
+
"tornado_chart_data": [
|
|
434
|
+
{"parameter": "fuel_cost_gas", "low": -300000.0, "high": 300000.0},
|
|
435
|
+
{"parameter": "wind_capacity", "low": -200000.0, "high": 200000.0}
|
|
436
|
+
]
|
|
437
|
+
}
|
|
438
|
+
*/
|
|
439
|
+
|
|
440
|
+
-- ============================================================================
|
|
441
|
+
-- DATA MANAGEMENT TRIGGERS
|
|
442
|
+
-- ============================================================================
|
|
443
|
+
|
|
444
|
+
-- Note: Access tracking for analysis cache would need to be handled in application code
|
|
445
|
+
-- SQLite doesn't support AFTER SELECT triggers
|
|
446
|
+
|
|
447
|
+
-- Note: Result size calculation should be handled in application code
|
|
448
|
+
-- Cannot modify NEW values in SQLite BEFORE INSERT triggers
|
|
449
|
+
|
|
450
|
+
-- Note: Timestamp updates should be handled in application code or with DEFAULT CURRENT_TIMESTAMP
|
|
451
|
+
-- SQLite triggers cannot update the same record being modified without recursion issues
|
|
452
|
+
|
|
453
|
+
-- ============================================================================
|
|
454
|
+
-- UTILITY VIEWS
|
|
455
|
+
-- ============================================================================
|
|
456
|
+
|
|
457
|
+
-- View for network analysis summary
|
|
458
|
+
CREATE VIEW network_analysis_summary AS
|
|
459
|
+
SELECT
|
|
460
|
+
n.id as network_id,
|
|
461
|
+
n.name as network_name,
|
|
462
|
+
COUNT(DISTINCT nac.analysis_type) as analysis_types_count,
|
|
463
|
+
COUNT(nac.id) as total_cache_entries,
|
|
464
|
+
SUM(nac.hit_count) as total_cache_hits,
|
|
465
|
+
SUM(nac.result_size_bytes) as total_cache_size_bytes,
|
|
466
|
+
MAX(nac.last_accessed) as last_analysis_accessed,
|
|
467
|
+
COUNT(or1.id) as optimization_runs_count,
|
|
468
|
+
MAX(or1.created_at) as last_optimization_run
|
|
469
|
+
FROM networks n
|
|
470
|
+
LEFT JOIN network_analysis_cache nac ON n.id = nac.network_id
|
|
471
|
+
LEFT JOIN optimization_results or1 ON n.id = or1.network_id
|
|
472
|
+
GROUP BY n.id, n.name;
|
|
473
|
+
|
|
474
|
+
-- View for recent network activity
|
|
475
|
+
CREATE VIEW network_activity_summary AS
|
|
476
|
+
SELECT
|
|
477
|
+
n.id as network_id,
|
|
478
|
+
n.name as network_name,
|
|
479
|
+
COUNT(DISTINCT c.id) as components_count,
|
|
480
|
+
COUNT(DISTINCT ca.id) as attributes_count,
|
|
481
|
+
COUNT(DISTINCT nn.id) as notes_count,
|
|
482
|
+
COUNT(DISTINCT nds.id) as data_store_entries_count,
|
|
483
|
+
MAX(c.updated_at) as last_component_update,
|
|
484
|
+
MAX(ca.updated_at) as last_attribute_update,
|
|
485
|
+
MAX(nn.updated_at) as last_note_update,
|
|
486
|
+
MAX(nds.updated_at) as last_data_update
|
|
487
|
+
FROM networks n
|
|
488
|
+
LEFT JOIN components c ON n.id = c.network_id
|
|
489
|
+
LEFT JOIN component_attributes ca ON c.id = ca.component_id
|
|
490
|
+
LEFT JOIN network_notes nn ON n.id = nn.network_id
|
|
491
|
+
LEFT JOIN network_data_store nds ON n.id = nds.network_id
|
|
492
|
+
GROUP BY n.id, n.name;
|
|
493
|
+
|
|
494
|
+
-- ============================================================================
|
|
495
|
+
-- CONNECTIVITY VIEWS - Human-readable bus connections
|
|
496
|
+
-- ============================================================================
|
|
497
|
+
|
|
498
|
+
-- View for components with single bus connections (generators, loads, etc.)
|
|
499
|
+
CREATE VIEW components_with_bus AS
|
|
500
|
+
SELECT
|
|
501
|
+
c.*,
|
|
502
|
+
b.name as bus_name
|
|
503
|
+
FROM components c
|
|
504
|
+
LEFT JOIN components b ON json_extract(c.connectivity, '$.bus_id') = b.id AND b.component_type = 'BUS'
|
|
505
|
+
WHERE c.component_type IN ('GENERATOR', 'LOAD', 'STORAGE_UNIT', 'STORE');
|
|
506
|
+
|
|
507
|
+
-- View for components with dual bus connections (lines, links)
|
|
508
|
+
CREATE VIEW components_with_buses AS
|
|
509
|
+
SELECT
|
|
510
|
+
c.*,
|
|
511
|
+
b0.name as bus0_name,
|
|
512
|
+
b1.name as bus1_name
|
|
513
|
+
FROM components c
|
|
514
|
+
LEFT JOIN components b0 ON json_extract(c.connectivity, '$.bus0_id') = b0.id AND b0.component_type = 'BUS'
|
|
515
|
+
LEFT JOIN components b1 ON json_extract(c.connectivity, '$.bus1_id') = b1.id AND b1.component_type = 'BUS'
|
|
516
|
+
WHERE c.component_type IN ('LINE', 'LINK');
|
|
517
|
+
|
|
518
|
+
-- Unified view for all components with resolved bus connections
|
|
519
|
+
CREATE VIEW components_with_connectivity AS
|
|
520
|
+
SELECT
|
|
521
|
+
c.*,
|
|
522
|
+
CASE
|
|
523
|
+
WHEN c.component_type = 'BUS' THEN NULL
|
|
524
|
+
WHEN c.component_type IN ('GENERATOR', 'LOAD', 'STORAGE_UNIT', 'STORE') THEN
|
|
525
|
+
(SELECT b.name FROM components b WHERE b.id = json_extract(c.connectivity, '$.bus_id') AND b.component_type = 'BUS')
|
|
526
|
+
ELSE NULL
|
|
527
|
+
END as bus_name,
|
|
528
|
+
CASE
|
|
529
|
+
WHEN c.component_type IN ('LINE', 'LINK') THEN
|
|
530
|
+
(SELECT b.name FROM components b WHERE b.id = json_extract(c.connectivity, '$.bus0_id') AND b.component_type = 'BUS')
|
|
531
|
+
ELSE NULL
|
|
532
|
+
END as bus0_name,
|
|
533
|
+
CASE
|
|
534
|
+
WHEN c.component_type IN ('LINE', 'LINK') THEN
|
|
535
|
+
(SELECT b.name FROM components b WHERE b.id = json_extract(c.connectivity, '$.bus1_id') AND b.component_type = 'BUS')
|
|
536
|
+
ELSE NULL
|
|
537
|
+
END as bus1_name
|
|
538
|
+
FROM components c;
|
|
539
|
+
|
|
540
|
+
-- ============================================================================
|
|
541
|
+
-- DEFAULT CARRIERS SETUP
|
|
542
|
+
-- ============================================================================
|
|
543
|
+
|
|
544
|
+
-- Note: Default carriers will be created automatically when a network is created
|
|
545
|
+
-- This is handled in the application code to ensure proper network_id assignment
|
|
546
|
+
-- The default carriers are:
|
|
547
|
+
-- - AC (default for electrical buses and components)
|
|
548
|
+
-- - DC (for DC electrical systems)
|
|
549
|
+
-- - heat (for heating systems)
|
|
550
|
+
-- - gas (for gas systems)
|
|
551
|
+
-- - electricity (generic electrical carrier)
|
|
552
|
+
|
|
553
|
+
-- These carriers follow PyPSA conventions and ensure all components can have
|
|
554
|
+
-- appropriate carrier assignments without requiring manual setup
|