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 Network formulation declared in data["formulations"] and the number of areas in data["areas"]:

  • Legacy fast path (Network = CopperPlateNetwork and len(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 by tests/test_zonal_legacy_regression.py).

  • Per-area Block path (Network = AreaTransportationModelNetwork or len(data["areas"]) > 1): not yet implemented in this commit; will be wired in commit #9b together with the builder refactor that lets each add_* 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 = AreaTransportationModelNetwork raises NotImplementedError (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 profiler attribute 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:

dict

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:

OptimizationResults

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:
  • level (int, optional) – Logging level threshold (e.g., logging.INFO, logging.DEBUG). Defaults to logging.INFO.

  • log_file (str, optional) – Path to a file where logs should be written. If None, logs only to console. Defaults to None.

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#

Mapping of log level names to ANSI color codes.

Type:

dict

RESET#

ANSI reset code to restore default terminal colors.

Type:

str

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:

str

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#