monee simulation

The public names below are re-exported from monee.simulation (e.g. from monee.simulation import run_timeseries, run_multi_period); the most common entry points are also available from the top-level monee package.

Single solve

monee.simulation.core.solve(net: monee.model.network.Network, optimization_problem: monee.problem.core.OptimizationProblem = None, solver=None, backend: str | None = None, formulation=None, simulation: bool = False, **kwargs)[source]

Solve net.

Parameters:
  • net (monee.model.network.Network) – The network to solve.

  • optimization_problem (monee.problem.core.OptimizationProblem) – Optional optimisation problem.

  • solver – Either a solver-name string ("ipopt", "gurobi", "scip", …), a concrete SolverInterface instance, or None (default - GEKKO+IPOPT).

  • backend (str | None) – "gekko" / "pyomo" to force the modelling backend. When None (default), the backend is auto-routed from solver.

  • formulation – Solve-time formulation - a registry key string ("smooth_nlp", "convex_miqcqp", "el_misocp", …), a NetworkFormulation, or a sequence of either (merged left to right). Overrides the network’s apply_formulation choice for this solve; components without any choice use DEFAULT_SIMULATION_FORMULATION.

  • simulation (bool) – When True solve as a square steady-state simulation (GEKKO IMODE=1, falling back to IMODE=3 if the model is not square); False (default) takes the optimize-the-feasibility-problem path. Ignored by backends without a simulation mode (e.g. Pyomo). Declared explicitly here so the flag does not ride silently through **kwargs; matches the backend solve default.

  • **kwargs – Forwarded to solver.solve(...).

Timeseries

class monee.simulation.timeseries.StepHook[source]

Bases: ABC

Pre/post-step callbacks for timeseries runs. Both methods are optional no-ops.

post_run(net: monee.model.network.Network, step: int, step_state: monee.solver.core.StepState, step_result: monee.simulation.timeseries.StepResult, base_net: monee.model.network.Network)[source]

Called after the step’s solve (success or failure).

Return type:

None

pre_run(base_net: monee.model.network.Network, step: int, step_state: monee.solver.core.StepState)[source]

Called before the per-step network copy and timeseries application.

Return type:

None

class monee.simulation.timeseries.StepResult(step: int, result: Any, failed: bool = False, skipped: bool = False, error: Exception | None = None)[source]

Bases: object

Outcome of a single timeseries step.

error: Exception | None = None
failed: bool = False
result: Any
skipped: bool = False
step: int
class monee.simulation.timeseries.TimeseriesData[source]

Bases: object

Time-varying attribute values applied to model objects before each step. All registered series must share a length (validated on add).

add_branch_series(branch_id, attribute: str, series)[source]

Register a time-varying attribute for a branch model (by id).

Return type:

None

add_branch_series_by_name(branch_name: str, attribute: str, series)[source]

Register a time-varying attribute for a branch model (by name).

Return type:

None

add_child_series(child_id, attribute: str, series)[source]

Register a time-varying attribute for a child model (by id).

Return type:

None

add_child_series_by_name(child_name: str, attribute: str, series)[source]

Register a time-varying attribute for a child model (by name).

Return type:

None

add_compound_series(compound_id, attribute: str, series)[source]

Register a time-varying attribute for a compound model (by id).

Return type:

None

add_compound_series_by_name(compound_name: str, attribute: str, series)[source]

Register a time-varying attribute for a compound model (by name).

Return type:

None

add_node_series(node_id, attribute: str, series)[source]

Register a time-varying attribute for a node model (by id).

Return type:

None

add_objective_data(child_id, attribute: str, series)[source]

Alias for add_child_series(); signals the attribute feeds an objective.

Return type:

None

add_objective_data_by_name(child_name: str, attribute: str, series)[source]

Like add_objective_data() but matches by component name.

Return type:

None

apply_to_branch(branch, timestep: int)[source]

Apply registered series values for branch at timestep.

Return type:

None

apply_to_child(child, timestep: int)[source]

Apply registered series values for child at timestep.

Return type:

None

apply_to_compound(compound, timestep: int)[source]

Apply registered series values for compound at timestep.

Return type:

None

apply_to_network(net: monee.model.network.Network, timestep: int)[source]

Apply all registered series to net at timestep.

Return type:

None

apply_to_node(node, timestep: int)[source]

Apply registered series values for node at timestep.

Return type:

None

property branch_id_data
property child_id_data
property child_name_data
property compound_id_data
extend(td: monee.simulation.timeseries.TimeseriesData)[source]

Merge td; self wins on attribute conflicts. Raises on length mismatch.

Return type:

None

classmethod from_dataframe(df: pandas.DataFrame, component_type: str, component_id=None, component_name: str = None)[source]

Build from a DataFrame (cols=attrs, rows=timesteps). component_type is node|child|branch|compound; pass id or name.

Return type:

monee.simulation.timeseries.TimeseriesData

property length: int | None

Number of timesteps, inferred from registered series lengths.

class monee.simulation.timeseries.TimeseriesResult(step_results: list[monee.simulation.timeseries.StepResult], datetime_index: pandas.DatetimeIndex | None = None)[source]

Bases: object

Per-step results. Failed steps are excluded from DataFrame queries but accessible via failed_steps.

property failed_steps: list[int]
get_result_for(model_type, attribute: str)[source]

DataFrame of attribute values: rows=steps, cols=component ids.

Return type:

pandas.DataFrame

get_result_for_id(component_id, attribute: str)[source]

Series of attribute for component_id across successful steps. Yields None where the component is absent (e.g. islanded out).

Return type:

pandas.Series

property raw: list

Successful SolverResult objects in step order (legacy; prefer step_results).

property step_results: list[StepResult]
summary()[source]
monee.simulation.timeseries.run(net: monee.model.network.Network, timeseries_data: monee.simulation.timeseries.TimeseriesData | None = None, steps: int | None = None, step_hooks: list[monee.simulation.timeseries.StepHook | collections.abc.Callable] | None = None, solver=None, backend: str | None = None, optimization_problem=None, solve_flag: bool = True, on_step_error: str = 'raise', progress_callback: collections.abc.Callable[[int, int], None] | None = None, datetime_index: pandas.DatetimeIndex | None = None, **solver_kwargs)[source]

Run a timeseries simulation: copy net, apply timeseries, solve, collect.

steps defaults to timeseries_data.length. on_step_error='skip' records a failed StepResult and continues. solver_kwargs are forwarded to solver.solve(...).

Return type:

monee.simulation.timeseries.TimeseriesResult

Step state

State carriers for timeseries (StepState - floats) and multi-period (PeriodState - live solver vars). Both expose the same get(comp_id, attr) / dt_h API so inter_step_equations works in both modes unchanged.

The implementations now live in monee.solver.core (the low-level layer both solver backends and the simulation engine depend on) to keep the dependency direction one-way and avoid a solver <-> simulation import cycle. This module re-exports them so the historical monee.simulation.step_state import path keeps working unchanged.

class monee.simulation.step_state.InterStepState[source]

Bases: ABC

Abstract base. step: negative = relative to current, non-negative = absolute.

dt_h: float = 1.0
abstractmethod get(component_id, attr: str, step: int = -1)[source]

Float (StepState) / live var (PeriodState), or None if no data.

has(component_id, attr: str)[source]
Return type:

bool

class monee.simulation.step_state.PeriodState(networks: list, current_t: int, dt_h: float = 1.0, initial_state: dict | None = None)[source]

Bases: InterStepState

All period networks (multi-period). get returns live solver vars after injection, so reading from another period becomes an algebraic cross-period constraint. Both past and future absolute indices are accessible.

Note

Absolute (non-negative) step indices are window-local under run_mpc(): self._networks is only the current rolling window’s networks, so step=0 means the first period of this window, not the global start of the run. This differs from StepState, whose absolute indices stay globally meaningful via its dropped-prefix bookkeeping. Relative (negative) lookbacks behave identically in both. Prefer relative indices in inter_step_equations if you need MPC-window-independent behaviour.

property T: int
get(component_id, attr: str, step: int = -1)[source]

Float (StepState) / live var (PeriodState), or None if no data.

class monee.simulation.step_state.StepState(initial_state: dict | None = None, max_steps: int | None = None)[source]

Bases: InterStepState

All previously-solved network copies (sequential timeseries). get returns floats.

initial_state falls back when no prior solve has written the attribute. max_steps caps how many solved networks are retained (None = unlimited): each network is a full copy, so an open-ended run (e.g. a Stepper paced by a co-simulation framework) would otherwise grow memory without bound. Absolute step indices keep their meaning when old networks are dropped; reading a dropped step falls back to initial_state.

get(component_id, attr: str, step: int = -1)[source]

Float (StepState) / live var (PeriodState), or None if no data.

push(net)[source]
Return type:

None

Multi-period

Multi-period optimization: build a single problem spanning T periods and solve in one shot. PeriodState exposes live solver variables behind the same API as StepState, so inter_step_equations works unchanged.

class monee.simulation.multi_period.GekkoMultiPeriodSolver(solver: int = 1)[source]

Bases: object

Multi-period optimizer on GEKKO/IPOPT. Two-pass: inject vars for all T periods, then assemble equations with a PeriodState that sees all periods so inter_step_equations can couple them freely.

solve_multi_period(network: monee.model.network.Network, timeseries_data: monee.simulation.timeseries.TimeseriesData | None = None, steps: int | None = None, optimization_problem=None, dt_h: float | list[float] = 1.0, datetime_index: pandas.DatetimeIndex | None = None, initial_state: dict | None = None, terminal_state: dict | None = None, formulation=None)[source]

Build and solve a multi-period optimization in one GEKKO model.

dt_h may be a list of length T (variable step size); datetime_index derives it from consecutive differences. initial_state / terminal_state pin attributes at t<0 / t=T-1.

Return type:

monee.simulation.multi_period.MultiPeriodResult

class monee.simulation.multi_period.MultiPeriodResult(net_copies: list[monee.model.network.Network], objective: float, success: bool, datetime_index: pandas.DatetimeIndex | None = None)[source]

Bases: object

Holds the outcome of a multi-period optimization.

One SolverResult-compatible network copy per period, all solved in a single solver invocation.

objective

Global objective value at the solution.

success

True if the solver reported a feasible solution.

property T: int
get_period_result(t: int)[source]

SolverResult for period t (objective is None; only the global MultiPeriodResult.objective is tracked).

Return type:

monee.solver.core.SolverResult

get_result_for(model_type, attribute: str)[source]

DataFrame of attribute: rows=periods, cols=component ids.

Return type:

pandas.DataFrame

get_result_for_id(component_id, attribute: str)[source]

Series of attribute for component_id across all periods.

Return type:

pandas.Series

class monee.simulation.multi_period.PyomoMultiPeriodSolver(solver_name: str = 'scip')[source]

Bases: object

Multi-period optimizer on Pyomo + pluggable MILP/NLP. Same two-pass structure as GekkoMultiPeriodSolver.

solve_multi_period(network: monee.model.network.Network, timeseries_data: monee.simulation.timeseries.TimeseriesData | None = None, steps: int | None = None, optimization_problem=None, dt_h: float | list[float] = 1.0, datetime_index: pandas.DatetimeIndex | None = None, initial_state: dict | None = None, terminal_state: dict | None = None, formulation=None)[source]

Build and solve a multi-period optimization in a single Pyomo model.

Return type:

monee.simulation.multi_period.MultiPeriodResult

monee.simulation.multi_period.run_mpc(network: monee.model.network.Network, timeseries_data: monee.simulation.timeseries.TimeseriesData | None = None, total_steps: int | None = None, horizon: int = 4, execution_steps: int = 1, solver=None, backend: str | None = None, optimization_problem=None, dt_h: float | list[float] = 1.0, datetime_index: pandas.DatetimeIndex | None = None, initial_state: dict | None = None, terminal_state: dict | None = None, formulation=None)[source]

Rolling-horizon MPC. Each iteration solves a horizon-period problem, accepts the first execution_steps periods, advances and reseeds initial state from the executed terminal state.

Note: returned objective is the sum of per-window values and overcounts when execution_steps < horizon.

Example:

result = run_mpc(
    net, td,
    total_steps=24,
    horizon=6,
    execution_steps=1,
    terminal_state={(bat_id, "e_mwh"): 4.0},
)
soc = result.get_result_for(mm.ElectricStorage, "e_mwh")
Return type:

monee.simulation.multi_period.MultiPeriodResult

monee.simulation.multi_period.run_multi_period(network: monee.model.network.Network, timeseries_data: monee.simulation.timeseries.TimeseriesData | None = None, steps: int | None = None, optimization_problem=None, solver=None, backend: str | None = None, dt_h: float | list[float] = 1.0, datetime_index: pandas.DatetimeIndex | None = None, initial_state: dict | None = None, terminal_state: dict | None = None, formulation=None)[source]

Run a single-shot multi-period optimisation. Cross-period coupling goes through the standard inter_step_equations protocol; TimeseriesData is applied per-period before equations are assembled.

Return type:

monee.simulation.multi_period.MultiPeriodResult

Stepper (co-simulation)

Stepper - externally-paced co-simulation adapter.

Steps a network forward in time at caller-supplied dt_h values (the external framework owns the clock), maintaining inter-step state (linepack, LTC, storage SoC, …) via the shared StepState plumbing. Each Stepper.step() works on a fresh network copy.

class monee.simulation.stepper.Stepper(net: monee.model.network.Network, *, solver=None, backend: str | None = None, optimization_problem=None, timeseries_data: monee.simulation.timeseries.TimeseriesData | None = None, initial_state: collections.abc.Mapping[tuple, float] | None = None, on_step_error: str = 'raise', max_history: int | None = None, **solver_kwargs: Any)[source]

Bases: object

Externally-paced co-simulation adapter. Holds base network, solver, optional problem and timeseries data, and the persistent StepState.

max_history caps how many solved steps are retained (None = unlimited): every step keeps a full solved network copy (once in the StepState, once in the StepResult history), so an open-ended co-simulation grows memory without bound otherwise. Set it to a small number (the longest lookback any inter_step_equations needs, e.g. 8) for long runs; to_timeseries_result() then only covers the retained window.

get(component_id, attr: str, step: int = -1)[source]

Solved value of attr on component component_id - by default from the most recent successful step (the get side of a co-simulation adapter’s set/step/get contract; data_overrides is the set side).

step follows StepState.get(): negative = relative to the latest solve, non-negative = absolute step index. Returns None (or the initial_state fallback) when no solve has written the value.

property history: list[StepResult]

Retained step results (the last max_history ones, or all).

reset(*, initial_state: collections.abc.Mapping[tuple, float] | None = None)[source]

Clear step history and recreate the StepState.

Return type:

None

property state: StepState
step(dt_h: float, *, data_overrides: collections.abc.Mapping[tuple, float] | None = None, ts_index: int | None = None)[source]

Advance by dt_h hours. data_overrides are applied after the ts_index slice (overrides win on conflicts).

Return type:

monee.simulation.timeseries.StepResult

property step_count: int

Total number of step() calls, including dropped and failed ones.

property t_h: float
to_timeseries_result(datetime_index: pandas.DatetimeIndex | None = None)[source]

Wrap the retained history as a TimeseriesResult. With max_history set this covers only the retained window.

Return type:

monee.simulation.timeseries.TimeseriesResult