Source code for chiller_sim.simulation.results

from __future__ import annotations

from dataclasses import dataclass

import numpy as np
from numpy.typing import NDArray


[docs] @dataclass(frozen=True) class OptimizeResult: """Output of a single optimization step.""" time_hours: float load_kw: float active_mask: NDArray[np.bool_] total_work_kw: float baseline_work_kw: float savings_fraction: float cop_array: NDArray[np.float64] temp_rise_array: NDArray[np.float64]
[docs] @dataclass class SimulationResult: """Aggregated results across all steps of a dynamic simulation.""" steps: list[OptimizeResult] @property def schedule(self) -> NDArray[np.bool_]: """Return 2-D boolean array of active masks, shape (n_steps, n_chillers).""" return np.array([s.active_mask for s in self.steps]) @property def total_work_kw(self) -> NDArray[np.float64]: """Return total work per step in kW, shape (n_steps,).""" return np.array([s.total_work_kw for s in self.steps]) @property def loads_kw(self) -> NDArray[np.float64]: """Return facility load per step in kW, shape (n_steps,).""" return np.array([s.load_kw for s in self.steps]) @property def savings_fraction(self) -> NDArray[np.float64]: """Return savings fraction per step, shape (n_steps,).""" return np.array([s.savings_fraction for s in self.steps]) @property def cop_arrays(self) -> NDArray[np.float64]: """Return per-chiller COP array per step, shape (n_steps, n_chillers).""" return np.array([s.cop_array for s in self.steps])
[docs] @dataclass(frozen=True) class InitialState: """Optional warm-start state for stream()/simulate() calls.""" active_mask: NDArray[np.bool_] time_since_start_hours: NDArray[np.float64]