pyconvexity 0.4.8__tar.gz → 0.4.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyconvexity might be problematic. Click here for more details.
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/PKG-INFO +1 -1
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/pyproject.toml +2 -2
- pyconvexity-0.4.9/src/pyconvexity/_version.py +1 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/pypsa/solver.py +27 -16
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/pypsa/storage.py +5 -11
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity.egg-info/PKG-INFO +1 -1
- pyconvexity-0.4.8/src/pyconvexity/_version.py +0 -1
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/README.md +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/setup.cfg +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/core/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/core/database.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/core/errors.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/core/types.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/dashboard.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/README.md +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/loaders/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/loaders/cache.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/schema/01_core_schema.sql +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/schema/02_data_metadata.sql +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/schema/03_validation_data.sql +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/sources/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/data/sources/gem.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/io/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/io/excel_exporter.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/io/excel_importer.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/io/netcdf_exporter.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/io/netcdf_importer.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/models/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/models/attributes.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/models/carriers.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/models/components.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/models/network.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/models/results.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/models/scenarios.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/pypsa/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/pypsa/api.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/pypsa/batch_loader.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/pypsa/builder.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/pypsa/clearing_price.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/solvers/pypsa/constraints.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/timeseries.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/validation/__init__.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity/validation/rules.py +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity.egg-info/SOURCES.txt +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity.egg-info/dependency_links.txt +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity.egg-info/requires.txt +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/src/pyconvexity.egg-info/top_level.txt +0 -0
- {pyconvexity-0.4.8 → pyconvexity-0.4.9}/tests/test_core_types.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyconvexity"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.9"
|
|
8
8
|
description = "Python library for energy system modeling and optimization with PyPSA"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -81,7 +81,7 @@ profile = "black"
|
|
|
81
81
|
line_length = 88
|
|
82
82
|
|
|
83
83
|
[tool.mypy]
|
|
84
|
-
python_version = "0.4.
|
|
84
|
+
python_version = "0.4.9"
|
|
85
85
|
warn_return_any = true
|
|
86
86
|
warn_unused_configs = true
|
|
87
87
|
disallow_untyped_defs = true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.9"
|
|
@@ -149,9 +149,17 @@ class NetworkSolver:
|
|
|
149
149
|
run_id = str(uuid.uuid4())
|
|
150
150
|
|
|
151
151
|
try:
|
|
152
|
-
#
|
|
152
|
+
# Extract PyPSA-specific options that shouldn't be passed to the solver
|
|
153
|
+
pypsa_options = {}
|
|
154
|
+
filtered_solver_options = solver_options.copy() if solver_options else {}
|
|
155
|
+
|
|
156
|
+
# linearized_unit_commitment is a PyPSA option, not a solver option
|
|
157
|
+
if filtered_solver_options.get('linearized_unit_commitment'):
|
|
158
|
+
pypsa_options['linearized_unit_commitment'] = filtered_solver_options.pop('linearized_unit_commitment')
|
|
159
|
+
|
|
160
|
+
# Get solver configuration (with filtered options)
|
|
153
161
|
actual_solver_name, solver_config = self._get_solver_config(
|
|
154
|
-
solver_name,
|
|
162
|
+
solver_name, filtered_solver_options if filtered_solver_options else None, custom_solver_config
|
|
155
163
|
)
|
|
156
164
|
|
|
157
165
|
# Resolve discount rate - fallback to 0.0 if None
|
|
@@ -197,19 +205,22 @@ class NetworkSolver:
|
|
|
197
205
|
# NOTE: Model constraints are applied DURING solve via extra_functionality
|
|
198
206
|
# Network constraints were already applied to the network structure before solve
|
|
199
207
|
|
|
208
|
+
# Build optimize kwargs
|
|
209
|
+
optimize_kwargs = {
|
|
210
|
+
'solver_name': actual_solver_name,
|
|
211
|
+
'multi_investment_periods': True,
|
|
212
|
+
'extra_functionality': extra_functionality,
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
# Add solver config if present
|
|
200
216
|
if solver_config:
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
result = network.optimize(
|
|
209
|
-
solver_name=actual_solver_name,
|
|
210
|
-
multi_investment_periods=True,
|
|
211
|
-
extra_functionality=extra_functionality,
|
|
212
|
-
)
|
|
217
|
+
optimize_kwargs.update(solver_config)
|
|
218
|
+
|
|
219
|
+
# Add PyPSA-specific options (like linearized_unit_commitment)
|
|
220
|
+
if pypsa_options:
|
|
221
|
+
optimize_kwargs.update(pypsa_options)
|
|
222
|
+
|
|
223
|
+
result = network.optimize(**optimize_kwargs)
|
|
213
224
|
|
|
214
225
|
solve_time = time.time() - start_time
|
|
215
226
|
|
|
@@ -385,7 +396,7 @@ class NetworkSolver:
|
|
|
385
396
|
mosek_default_options = {
|
|
386
397
|
"solver_options": {
|
|
387
398
|
"MSK_DPAR_MIO_REL_GAP_CONST": 0.05, # MIP relative gap tolerance (5% to match Gurobi)
|
|
388
|
-
"
|
|
399
|
+
"MSK_DPAR_MIO_MAX_TIME": 36000, # Max time 10 hours
|
|
389
400
|
}
|
|
390
401
|
}
|
|
391
402
|
if solver_options:
|
|
@@ -448,7 +459,7 @@ class NetworkSolver:
|
|
|
448
459
|
mosek_defaults = {
|
|
449
460
|
"solver_options": {
|
|
450
461
|
"MSK_DPAR_MIO_REL_GAP_CONST": 0.05, # Match Gurobi 5% MIP gap (was 1e-4)
|
|
451
|
-
"
|
|
462
|
+
"MSK_DPAR_MIO_MAX_TIME": 36000, # Max time 10 hours
|
|
452
463
|
"MSK_IPAR_NUM_THREADS": 0, # Use all cores (0 = auto)
|
|
453
464
|
}
|
|
454
465
|
}
|
|
@@ -4,12 +4,16 @@ Result storage functionality for PyPSA solver integration.
|
|
|
4
4
|
Handles storing solve results back to the database with proper validation and error handling.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import logging
|
|
7
8
|
import uuid
|
|
8
9
|
import pandas as pd
|
|
9
10
|
import numpy as np
|
|
10
11
|
from typing import Dict, Any, Optional, Callable
|
|
11
12
|
|
|
12
13
|
from pyconvexity.core.types import StaticValue
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
13
17
|
from pyconvexity.models import (
|
|
14
18
|
list_components_by_type,
|
|
15
19
|
set_static_attribute,
|
|
@@ -220,7 +224,6 @@ class ResultStorage:
|
|
|
220
224
|
Returns:
|
|
221
225
|
Number of buses with clearing prices stored
|
|
222
226
|
"""
|
|
223
|
-
logger.info(f"=== CALCULATING AND STORING CLEARING PRICES (scenario_id={scenario_id}) ===")
|
|
224
227
|
|
|
225
228
|
try:
|
|
226
229
|
from .clearing_price import ClearingPriceCalculator
|
|
@@ -233,21 +236,14 @@ class ResultStorage:
|
|
|
233
236
|
return 0
|
|
234
237
|
|
|
235
238
|
# Log what we got from the calculator
|
|
236
|
-
logger.info(f"Clearing prices calculated for {len(clearing_prices)} buses")
|
|
237
239
|
for bus_name, prices in clearing_prices.items():
|
|
238
240
|
n_zeros = np.sum(prices == 0)
|
|
239
241
|
n_inf = np.sum(np.isinf(prices))
|
|
240
242
|
valid = prices[(prices > 0) & np.isfinite(prices)]
|
|
241
|
-
|
|
242
|
-
logger.info(f" {bus_name}: {len(prices)} periods, mean=£{np.mean(valid):.2f}, "
|
|
243
|
-
f"zeros={n_zeros}, inf={n_inf}, range=[£{np.min(valid):.2f}, £{np.max(valid):.2f}]")
|
|
244
|
-
else:
|
|
245
|
-
logger.warning(f" {bus_name}: {len(prices)} periods, ALL ZERO OR INF (zeros={n_zeros}, inf={n_inf})")
|
|
246
|
-
|
|
243
|
+
|
|
247
244
|
# Get bus component IDs
|
|
248
245
|
buses = list_components_by_type(conn, "BUS")
|
|
249
246
|
bus_name_to_id = {bus.name: bus.id for bus in buses}
|
|
250
|
-
logger.info(f"Found {len(buses)} buses in database: {list(bus_name_to_id.keys())}")
|
|
251
247
|
|
|
252
248
|
stored_count = 0
|
|
253
249
|
for bus_name, prices in clearing_prices.items():
|
|
@@ -268,14 +264,12 @@ class ResultStorage:
|
|
|
268
264
|
conn, bus_id, "clearing_price", values, scenario_id
|
|
269
265
|
)
|
|
270
266
|
stored_count += 1
|
|
271
|
-
logger.info(f" ✅ {bus_name} (id={bus_id}): stored {len(values)} clearing prices")
|
|
272
267
|
except Exception as e:
|
|
273
268
|
logger.error(f" ❌ {bus_name} (id={bus_id}): failed to store clearing_price: {e}")
|
|
274
269
|
import traceback
|
|
275
270
|
traceback.print_exc()
|
|
276
271
|
continue
|
|
277
272
|
|
|
278
|
-
logger.info(f"=== CLEARING PRICES: Stored {stored_count}/{len(clearing_prices)} buses ===")
|
|
279
273
|
return stored_count
|
|
280
274
|
|
|
281
275
|
except ImportError as e:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.4.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|