Skip to content

hybrid_oscillator

Hybrid oscillator benchmark.

hybrid_oscillator(damping_left=0.2, damping_right=0.1, frequency=2.0, initial_state=None)

Create a piecewise damped oscillator benchmark.

Parameters:

Name Type Description Default
damping_left float

Damping for the left half-space.

0.2
damping_right float

Damping for the right half-space.

0.1
frequency float

Oscillation frequency.

2.0
initial_state ndarray | None

Optional initial [position, velocity].

None

Returns:

Type Description
HybridSystem

HybridSystem configured for a hybrid oscillator.

Source code in src/flowcean/hybrid/benchmarks/hybrid_oscillator.py
 17
 18
 19
 20
 21
 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
def hybrid_oscillator(
    damping_left: float = 0.2,
    damping_right: float = 0.1,
    frequency: float = 2.0,
    initial_state: np.ndarray | None = None,
) -> HybridSystem:
    """Create a piecewise damped oscillator benchmark.

    Args:
        damping_left: Damping for the left half-space.
        damping_right: Damping for the right half-space.
        frequency: Oscillation frequency.
        initial_state: Optional initial [position, velocity].

    Returns:
        HybridSystem configured for a hybrid oscillator.
    """

    def flow_left(
        _t: float,
        state: np.ndarray,
        params: Parameters,
        _input_stream: InputStream,
    ) -> np.ndarray:
        position, velocity = state
        return np.array(
            [
                velocity,
                -(params["frequency"] ** 2) * position
                - params["damping_left"] * velocity,
            ],
        )

    def flow_right(
        _t: float,
        state: np.ndarray,
        params: Parameters,
        _input_stream: InputStream,
    ) -> np.ndarray:
        position, velocity = state
        return np.array(
            [
                velocity,
                -(params["frequency"] ** 2) * position
                - params["damping_right"] * velocity,
            ],
        )

    def event_surface_right(
        _t: float,
        state: np.ndarray,
        _parameters: Parameters,
        _input_stream: InputStream,
    ) -> float:
        return state[0]

    def event_surface_left(
        _t: float,
        state: np.ndarray,
        _parameters: Parameters,
        _input_stream: InputStream,
    ) -> float:
        return state[0]

    left_dynamics = ContinuousDynamics(flow_left, label="left")
    right_dynamics = ContinuousDynamics(flow_right, label="right")
    left = Location(left_dynamics, label="left")
    right = Location(right_dynamics, label="right")

    to_right = Transition(
        source=left,
        target=right,
        event=EventSurface(
            event_surface_right,
            direction=CrossingDirection.RISING,
            label="cross_right",
        ),
    )
    to_left = Transition(
        source=right,
        target=left,
        event=EventSurface(
            event_surface_left,
            direction=CrossingDirection.FALLING,
            label="cross_left",
        ),
    )

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

    return HybridSystem(
        locations=[left, right],
        transitions=[to_right, to_left],
        initial_location=left,
        initial_state=initial_state,
        parameters={
            "damping_left": damping_left,
            "damping_right": damping_right,
            "frequency": frequency,
        },
    )