Skip to content

thermostat

Thermostat benchmark.

thermostat(ambient=20.0, heating_power=5.0, cooling_rate=0.3, hysteresis=2.0, initial_state=None)

Create a thermostat benchmark system.

Parameters:

Name Type Description Default
ambient float

Ambient temperature.

20.0
heating_power float

Heating input strength.

5.0
cooling_rate float

Cooling coefficient.

0.3
hysteresis float

Temperature hysteresis band width.

2.0
initial_state ndarray | None

Optional initial temperature.

None

Returns:

Type Description
HybridSystem

HybridSystem configured for thermostat switching.

Source code in src/flowcean/hybrid/benchmarks/thermostat.py
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def thermostat(
    ambient: float = 20.0,
    heating_power: float = 5.0,
    cooling_rate: float = 0.3,
    hysteresis: float = 2.0,
    initial_state: np.ndarray | None = None,
) -> HybridSystem:
    """Create a thermostat benchmark system.

    Args:
        ambient: Ambient temperature.
        heating_power: Heating input strength.
        cooling_rate: Cooling coefficient.
        hysteresis: Temperature hysteresis band width.
        initial_state: Optional initial temperature.

    Returns:
        HybridSystem configured for thermostat switching.
    """

    def heating(
        _t: float,
        state: np.ndarray,
        params: Parameters,
        _input_stream: InputStream,
    ) -> np.ndarray:
        temperature = state[0]
        return np.array(
            [
                -params["cooling_rate"] * (temperature - params["ambient"])
                + params["heating_power"],
            ],
        )

    def cooling(
        _t: float,
        state: np.ndarray,
        params: Parameters,
        _input_stream: InputStream,
    ) -> np.ndarray:
        temperature = state[0]
        return np.array(
            [
                -params["cooling_rate"] * (temperature - params["ambient"]),
            ],
        )

    def event_surface_high(
        t: float,
        state: np.ndarray,
        params: Parameters,
        input_stream: InputStream,
    ) -> float:
        target = float(input_stream(t)[0])
        return state[0] - (target + 0.5 * params["hysteresis"])

    def event_surface_low(
        t: float,
        state: np.ndarray,
        params: Parameters,
        input_stream: InputStream,
    ) -> float:
        target = float(input_stream(t)[0])
        return state[0] - (target - 0.5 * params["hysteresis"])

    heating_dynamics = ContinuousDynamics(heating, label="heating")
    cooling_dynamics = ContinuousDynamics(cooling, label="cooling")
    heating_mode = Location(heating_dynamics, label="heating")
    cooling_mode = Location(cooling_dynamics, label="cooling")

    to_cooling = Transition(
        source=heating_mode,
        target=cooling_mode,
        event=EventSurface(
            event_surface_high,
            direction=CrossingDirection.RISING,
            label="too_hot",
        ),
    )
    to_heating = Transition(
        source=cooling_mode,
        target=heating_mode,
        event=EventSurface(
            event_surface_low,
            direction=CrossingDirection.FALLING,
            label="too_cold",
        ),
    )

    if initial_state is None:
        initial_state = np.array([ambient], dtype=float)

    return HybridSystem(
        locations=[heating_mode, cooling_mode],
        transitions=[to_cooling, to_heating],
        initial_location=heating_mode,
        initial_state=initial_state,
        parameters={
            "ambient": ambient,
            "heating_power": heating_power,
            "cooling_rate": cooling_rate,
            "hysteresis": hysteresis,
        },
    )