|
| 1 | +from pythonfmu3 import Fmi3Causality, Fmi3Variability, Fmi3SlaveBase, ModelExchange, Fmi3Status, Float64, Fmi3Initial, Unit, Float64Type, Fmi3StepResult |
| 2 | + |
| 3 | +from typing import List |
| 4 | + |
| 5 | + |
| 6 | +EVENT_EPS = 1e-12 |
| 7 | + |
| 8 | +class BouncingBall(Fmi3SlaveBase, ModelExchange): |
| 9 | + |
| 10 | + def __init__(self, **kwargs): |
| 11 | + super().__init__(**kwargs) |
| 12 | + |
| 13 | + self.author = "..." |
| 14 | + self.description = "Bouncing Ball" |
| 15 | + |
| 16 | + self.time = 0.0 |
| 17 | + self.h = 1.0 |
| 18 | + self.v = 0.0 |
| 19 | + self.derh = 0.0 |
| 20 | + self.derv = 0.0 |
| 21 | + self.g = -9.81 |
| 22 | + self.e = 0.7 |
| 23 | + self.v_min = 0.1 |
| 24 | + |
| 25 | + # define units |
| 26 | + unit1 = Unit(name="m", m=1) |
| 27 | + unit2 = Unit(name="m/s", m=1, s=-1) |
| 28 | + unit3 = Unit(name="m/s2", m=1, s=-2) |
| 29 | + self.register_units([unit1, unit2, unit3]) |
| 30 | + |
| 31 | + |
| 32 | + self.register_variable(Float64("time", causality=Fmi3Causality.independent, variability=Fmi3Variability.continuous)) |
| 33 | + |
| 34 | + self.register_variable(Float64("ball.h", causality=Fmi3Causality.output, start=1, variability=Fmi3Variability.continuous, initial=Fmi3Initial.exact, unit=unit1.name), |
| 35 | + nested=False, has_event_indicator=True) |
| 36 | + self.register_variable(Float64("ball.derh", causality=Fmi3Causality.local, variability=Fmi3Variability.continuous, derivative=1, unit=unit2.name), |
| 37 | + nested=False) |
| 38 | + self.register_variable(Float64("ball.v", causality=Fmi3Causality.output, start=0, variability=Fmi3Variability.continuous, initial=Fmi3Initial.exact, unit=unit2.name), |
| 39 | + nested=False) |
| 40 | + self.register_variable(Float64("ball.derv", causality=Fmi3Causality.local, variability=Fmi3Variability.continuous, derivative=3, unit=unit3.name), |
| 41 | + nested=False) |
| 42 | + |
| 43 | + self.register_variable(Float64("g", causality=Fmi3Causality.parameter, variability=Fmi3Variability.fixed, unit=unit3.name)) |
| 44 | + self.register_variable(Float64("e", causality=Fmi3Causality.parameter, variability=Fmi3Variability.tunable)) |
| 45 | + self.register_variable(Float64("v_min", variability=Fmi3Variability.constant, start=0.1)) |
| 46 | + |
| 47 | + |
| 48 | + |
| 49 | + def get_continuous_state_derivatives(self) -> List[float]: |
| 50 | + self.derh = self.v |
| 51 | + self.derv = self.g |
| 52 | + |
| 53 | + def get_event_indicators(self) -> List[float]: |
| 54 | + z = [self.h] |
| 55 | + if self.h > -EVENT_EPS and self.h <=0 and self.v > 0: |
| 56 | + z[0] = -EVENT_EPS |
| 57 | + |
| 58 | + return [self.h - 0.0] |
| 59 | + |
| 60 | + def update_discrete_states(self): |
| 61 | + discrete_states_need_update = False |
| 62 | + terminate_simulation = False |
| 63 | + nominals_of_continuous_states_changed = False |
| 64 | + values_of_continuous_states_changed = False |
| 65 | + next_event_time_defined = False |
| 66 | + next_event_time = 0.0 |
| 67 | + |
| 68 | + if self.h <= 0 and self.v < 0: |
| 69 | + self.v = -self.e * self.v |
| 70 | + if abs(self.v) < self.v_min: |
| 71 | + self.v = 0.0 |
| 72 | + terminate_simulation = True |
| 73 | + discrete_states_need_update = True |
| 74 | + |
| 75 | + return Fmi3Status.ok, discrete_states_need_update, terminate_simulation |
0 commit comments