Top-level results container returned by EnergySystem.optimize(). Provides access to generator, storage, and market dispatch results, solver status, and objective value.
See Results in the User Guide for a full walkthrough.
classOptimalDispatchResults:"""Dispatch results of one solve: the solver status, the objective value and one dispatch per entity type."""__slots__=("_dispatches","_has_solution","_objective_value","_solution","_solver_status","_termination_condition",)def__init__(self,outcome:SolveOutcome,build_dispatches:Callable[[xr.Dataset],Sequence[Dispatch]],)->None:"""Initialize from the solve outcome and the function that reads the dispatches from its solution. Args: outcome: What the solver returned. build_dispatches: Returns one dispatch per entity type from the solution (`OptimizationProblem.dispatches`); called only when the outcome has a solution. It gets the solution with its scenario dimension, and each dispatch is squeezed afterwards: derived series such as the flexible-load actual load add scenario-indexed parameters, which would broadcast the dimension back if the solution were squeezed first. """self._solver_status=outcome.statusself._termination_condition=outcome.termination_conditionself._has_solution=outcome.has_solutionself._objective_value=outcome.objective_valueself._solution=_without_single_scenario(outcome.solution)dispatches=build_dispatches(outcome.solution)ifoutcome.has_solutionelse()self._dispatches:dict[type[Dispatch],Dispatch]={type(dispatch):type(dispatch)(_without_single_scenario(dispatch.to_dataset()),dispatch.dimension)fordispatchindispatches}@propertydefsolver_status(self)->SolveStatus:"""Get the solver status."""returnself._solver_status@propertydeftermination_condition(self)->str:"""Get the termination condition."""returnself._termination_conditiondefto_dataset(self)->xr.Dataset:"""Get the raw solution dataset."""self._validate_terminated_successfully()returnself._solutiondef_validate_terminated_successfully(self)->None:ifnotself._has_solution:msg=f"No solution available. Optimization Termination Condition: {self._termination_condition}."raiseOdysSolverError(msg)def_dispatch_of(self,kind:type[DispatchT])->DispatchT:self._validate_terminated_successfully()dispatch=self._dispatches.get(kind)ifnotisinstance(dispatch,kind):msg=f"This model does not contain {kind.label} results"raiseOdysNoResultsError(msg)returndispatch@propertydefgenerators(self)->GeneratorDispatch:"""Get generator dispatch results."""returnself._dispatch_of(GeneratorDispatch)@propertydefbattery_storages(self)->BatteryStorageDispatch:"""Get battery storage dispatch results."""returnself._dispatch_of(BatteryStorageDispatch)@propertydefelectric_vehicles(self)->ElectricVehicleDispatch:"""Get electric vehicle dispatch results."""returnself._dispatch_of(ElectricVehicleDispatch)@propertydefchargers(self)->ChargerDispatch:"""Get charger dispatch results."""returnself._dispatch_of(ChargerDispatch)@propertydefmarkets(self)->MarketDispatch:"""Get market dispatch results."""returnself._dispatch_of(MarketDispatch)@propertydefflexible_loads(self)->FlexibleLoadDispatch:"""Get flexible load dispatch results."""returnself._dispatch_of(FlexibleLoadDispatch)@propertydefobjective_value(self)->float|None:"""Objective value from optimization."""self._validate_terminated_successfully()returnself._objective_value
Returns one dispatch per entity type from the solution
(OptimizationProblem.dispatches); called only when the outcome has a solution.
It gets the solution with its scenario dimension, and each dispatch is squeezed
afterwards: derived series such as the flexible-load actual load add scenario-indexed
parameters, which would broadcast the dimension back if the solution were squeezed first.
required
Source code in src/odys/results/optimization_results.py
def__init__(self,outcome:SolveOutcome,build_dispatches:Callable[[xr.Dataset],Sequence[Dispatch]],)->None:"""Initialize from the solve outcome and the function that reads the dispatches from its solution. Args: outcome: What the solver returned. build_dispatches: Returns one dispatch per entity type from the solution (`OptimizationProblem.dispatches`); called only when the outcome has a solution. It gets the solution with its scenario dimension, and each dispatch is squeezed afterwards: derived series such as the flexible-load actual load add scenario-indexed parameters, which would broadcast the dimension back if the solution were squeezed first. """self._solver_status=outcome.statusself._termination_condition=outcome.termination_conditionself._has_solution=outcome.has_solutionself._objective_value=outcome.objective_valueself._solution=_without_single_scenario(outcome.solution)dispatches=build_dispatches(outcome.solution)ifoutcome.has_solutionelse()self._dispatches:dict[type[Dispatch],Dispatch]={type(dispatch):type(dispatch)(_without_single_scenario(dispatch.to_dataset()),dispatch.dimension)fordispatchindispatches}