Core Optimization Functions#
Main functions for running SDOM optimizations.
Model Initialization#
- sdom.optimization_main.initialize_model(data, n_hours=8760, with_resilience_constraints=False, model_name='SDOM_Model')[source]#
Initialize a Pyomo SDOM optimization model (dispatcher).
Selects the model-construction path based on the
Networkformulation declared indata["formulations"]and the number of areas indata["areas"]:Legacy fast path (
Network = CopperPlateNetworkandlen(data["areas"]) == 1): delegates to_initialize_model_copperplate(), which is the historical model body preserved verbatim. This guarantees bit-identical objective values for every legacy data folder (locked bytests/test_zonal_legacy_regression.py).Per-area Block path (
Network = AreaTransportationModelNetworkorlen(data["areas"]) > 1): not yet implemented in this commit; will be wired in commit #9b together with the builder refactor that lets eachadd_*consume a per-area data slice.
- Parameters:
data (dict) – Data dictionary as returned by
sdom.io_manager.load_data(). Must contain"formulations"and"areas"keys.n_hours (int, optional) – Number of hours to simulate (default 8760).
with_resilience_constraints (bool, optional) – If True, adds resilience-related constraints. Combined with
Network = AreaTransportationModelNetworkraisesNotImplementedError(deferred per PRD).model_name (str, optional) – Name to assign to the Pyomo model instance (default
"SDOM_Model").
- Returns:
A fully initialized Pyomo model ready for optimization, with a
profilerattribute attached.- Return type:
pyomo.environ.ConcreteModel
- Raises:
NotImplementedError – When the per-area Block path is required (zonal data or
Network = AreaTransportationModelNetwork). This branch lands in commit #9b.
Solver Configuration#
- sdom.optimization_main.get_default_solver_config_dict(solver_name='cbc', executable_path='.\\Solver\\bin\\cbc.exe', *, mip_gap=0.002, time_limit=None, stream_solver_output=False)[source]#
Generate a default solver configuration dictionary with standard SDOM settings.
Creates a pre-configured dictionary for solver initialization with recommended settings for SDOM optimization problems. Includes solver options and solve keywords for controlling optimization behavior.
- Parameters:
solver_name (str, optional) –
Solver to use. Supported values:
’cbc’: COIN-OR CBC open-source MILP solver (requires executable_path)
’highs’: HiGHS open-source MILP solver (uses appsi interface)
’xpress’: FICO Xpress commercial solver (requires license)
Default is ‘cbc’.
executable_path (str, optional) – Path to solver executable file. Required for CBC solver. Default is ‘.Solverbincbc.exe’.
mip_gap (float, optional) – MIP relative optimality gap tolerance. Default is 0.002 (0.2%).
time_limit (float, optional) – Maximum solve time in seconds. Default is None (no limit).
stream_solver_output (bool, optional) – Whether to stream solver native output live to stdout via
tee. Default is False.
- Returns:
Configuration dictionary with keys:
’solver_name’ (str): Solver identifier for SolverFactory
’executable_path’ (str): Path to executable (CBC only)
’options’ (dict): Solver-specific options
’solve_keywords’ (dict): Arguments for solver.solve() call
- Return type:
Notes
Solver-specific option mappings:
HiGHS: Uses ‘mip_rel_gap’ for MIP gap
Xpress: Uses ‘miprelstop’ for MIP gap, ‘maxtime’ for time limit
CBC: Uses ‘ratioGap’ for MIP gap
Examples
>>> # Using HiGHS (open-source) >>> config = get_default_solver_config_dict(solver_name="highs") >>> solver = configure_solver(config)
>>> # Using Xpress (commercial, requires license) >>> config = get_default_solver_config_dict( ... solver_name="xpress", ... mip_gap=0.001, ... time_limit=3600, ... ) >>> solver = configure_solver(config)
- sdom.optimization_main.configure_solver(solver_config_dict: dict)[source]#
Configure and instantiate a Pyomo solver based on configuration dictionary.
Creates a SolverFactory instance with the specified solver and applies any provided options. Handles solver-specific initialization (e.g., executable paths for CBC, license initialization for Xpress).
- Parameters:
solver_config_dict (dict) –
Configuration dictionary containing:
’solver_name’ (str): Solver identifier (e.g., ‘cbc’, ‘appsi_highs’, ‘xpress_direct’, ‘gurobi’)
’executable_path’ (str): Path to solver executable (required for CBC, optional for others)
’options’ (dict): Solver-specific options to apply (e.g., miprelstop, outputlog)
- Returns:
Configured Pyomo solver instance ready to solve optimization models.
- Return type:
solver
- Raises:
RuntimeError – If the specified solver is not available on the system.
Notes
CBC solver requires explicit executable_path.
Xpress uses xpress_direct interface and requires a valid license.
HiGHS and other solvers use system PATH or Python package installation.
Examples
>>> config = get_default_solver_config_dict(solver_name="xpress") >>> solver = configure_solver(config)
Running Optimization#
- sdom.optimization_main.run_solver(model, solver_config_dict: dict, case_name: str = 'run') OptimizationResults[source]#
Solve the optimization model and return structured results.
Solves the given optimization model using the configured solver and collects all results into an OptimizationResults dataclass.
- Parameters:
model (pyomo.core.base.PyomoModel.ConcreteModel) – The Pyomo optimization model to be solved. The model must have an attribute ‘GenMix_Target’ that can be set.
solver_config_dict (dict) – Solver configuration dictionary from get_default_solver_config_dict().
case_name (str, optional) – Case identifier for labeling results. Defaults to “run”.
- Returns:
A dataclass containing all optimization results including: - termination_condition: Solver termination status - total_cost: Objective value - generation_df: Hourly generation dispatch DataFrame - storage_df: Hourly storage operation DataFrame - summary_df: Summary metrics DataFrame - capacity: Installed capacities by technology - storage_capacity: Storage capacities (charge, discharge, energy) - cost_breakdown: Detailed cost breakdown - problem_info: Solver problem information
- Return type:
- Raises:
RuntimeError – If the solver is not available on the system.
Notes
If the solver does not find an optimal solution, the returned OptimizationResults will have is_optimal=False and minimal data populated.
Configuration#
- sdom.config_sdom.configure_logging(level=20, log_file=None)[source]#
Configure the logging system with colored console output and optional file logging.
Sets up logging handlers with color-coded formatting for terminal output. Optionally writes logs to a file as well. Should be called once at the start of SDOM execution.
- Parameters:
- Returns:
None
Notes
The format includes timestamp and log level: ‘YYYY-MM-DD HH:MM:SS-new line-LEVEL - message’ Color formatting is applied via the ColorFormatter class using ANSI codes. Multiple calls will reconfigure the logging system.
- class sdom.config_sdom.ColorFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]#
Custom logging formatter that adds color codes to log level names.
This formatter applies ANSI color codes to different log levels for improved readability in terminal output. Colors are defined in the LOG_COLORS constant.
- COLORS = {'CRITICAL': '\x1b[91m', 'DEBUG': '\x1b[94m', 'ERROR': '\x1b[91m', 'INFO': '\x1b[92m', 'WARNING': '\x1b[93m'}#
- RESET = '\x1b[0m'#
- format(record)[source]#
Apply color formatting to log record level names.
- Parameters:
record (logging.LogRecord) – The log record to format.
- Returns:
The formatted log message with colored level name.
- Return type:
Example Usage#
from sdom import (
load_data,
initialize_model,
get_default_solver_config_dict,
run_solver,
export_results
)
# Load data
data = load_data('./Data/scenario/')
# Initialize model
model = initialize_model(
data=data,
n_hours=8760,
with_resilience_constraints=False
)
# Configure solver
solver_config = get_default_solver_config_dict(
solver_name="cbc",
executable_path="./Solver/bin/cbc.exe"
)
# Run optimization - returns OptimizationResults object
results = run_solver(model, solver_config)
# Check if solution is optimal
if results.is_optimal:
print(f"Total Cost: ${results.total_cost:,.2f}")
print(f"Wind Capacity: {results.total_cap_wind:.2f} MW")
print(f"Solar Capacity: {results.total_cap_pv:.2f} MW")
# Access storage capacities
for tech, cap in results.total_cap_storage_charge.items():
print(f"{tech} Capacity: {cap:.2f} MW")
# Export results to CSV files
export_results(results, case="scenario_1")
else:
print(f"Optimization failed: {results.termination_condition}")
See Also#
Results Module - Full documentation of the
OptimizationResultsclassData I/O Manager - Data loading and result export functions