Skip to content

impact_oscillator

Impact oscillator benchmark with periodic forcing.

impact_oscillator(damping=0.1, stiffness=4.0, forcing=0.5, forcing_freq=1.5, restitution=0.7, initial_state=None)

Create an impact oscillator with time-dependent forcing.

Parameters:

Name Type Description Default
damping float

Linear damping coefficient.

0.1
stiffness float

Spring stiffness.

4.0
forcing float

Forcing amplitude.

0.5
forcing_freq float

Forcing frequency.

1.5
restitution float

Velocity multiplier on impact.

0.7
initial_state ndarray | None

Optional initial [position, velocity].

None

Returns:

Type Description
HybridSystem

HybridSystem configured for an impact oscillator.

Source code in src/flowcean/hybrid/benchmarks/impact_oscillator.py
 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
126
127
128
129
130
def impact_oscillator(
    damping: float = 0.1,
    stiffness: float = 4.0,
    forcing: float = 0.5,
    forcing_freq: float = 1.5,
    restitution: float = 0.7,
    initial_state: np.ndarray | None = None,
) -> HybridSystem:
    """Create an impact oscillator with time-dependent forcing.

    Args:
        damping: Linear damping coefficient.
        stiffness: Spring stiffness.
        forcing: Forcing amplitude.
        forcing_freq: Forcing frequency.
        restitution: Velocity multiplier on impact.
        initial_state: Optional initial [position, velocity].

    Returns:
        HybridSystem configured for an impact oscillator.
    """

    def flow(
        t: float,
        state: np.ndarray,
        params: Parameters,
        input_stream: InputStream,
    ) -> np.ndarray:
        position, velocity = state
        periodic_forcing = _forcing(t, params, input_stream)
        accel = (
            -params["stiffness"] * position
            - params["damping"] * velocity
            + periodic_forcing
        )
        return np.array([velocity, accel], dtype=float)

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

    def reset(
        _t: float,
        state: np.ndarray,
        params: Parameters,
        _input_stream: InputStream,
    ) -> np.ndarray:
        position, velocity = state
        return np.array(
            [position, -params["restitution"] * velocity],
            dtype=float,
        )

    dynamics = ContinuousDynamics(flow, label="oscillate")
    location = Location(
        dynamics,
        label="oscillate",
        parameters={"restitution": restitution},
    )
    transition = Transition(
        source=location,
        target=location,
        event=EventSurface(
            event_surface,
            direction=CrossingDirection.FALLING,
            label="impact",
        ),
        reset=Reset(
            reset,
            label="bounce",
        ),
    )

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

    return HybridSystem(
        locations=[location],
        transitions=[transition],
        initial_location=location,
        initial_state=initial_state,
        parameters={
            "damping": damping,
            "stiffness": stiffness,
            "forcing": forcing,
            "forcing_freq": forcing_freq,
        },
    )