Regenerative braking
A car braked by a Faraday disk generator on its wheel, which charges a supercapacitor.
- Name:
regenerative_braking - Field:
engineering/power_systems - Formalism: ordinary differential equations
- References: Trzaska 2023
Factory
@register_model(
field='engineering/power_systems',
tags=('energy', 'electromechanics', 'vehicles', 'ode'),
references=('Trzaska 2023',),
defaults={'until': 60.0, 'dt': 0.5},
)
def regenerative_braking(
v: float = 20.0,
*,
m: float = 1000.0,
A: float = 1.2,
L: float = 0.01,
R: float = 0.05,
C: float = 680.0,
alpha: float = 50.0,
beta: float = 5.0,
) -> System:
"""Return a car braked by a Faraday disk generator on its wheel, which charges a supercapacitor.
The disk generates the voltage `A v`, with the structural constant `A = |B| R^2 / (2 r_w)` of the disk and the
wheel, and drives the current through an inductor and a resistor into a supercapacitor,
`L I' = A v - R I - V_s` and `C V_s' = I`. The current brakes the car with the force `A I`, together with dry and
viscous friction, `m v' = -A I - alpha sign(v) - β v`, so the kinetic energy of the car ends up in the capacitor
and in the losses.
Args:
v:
The initial speed of the car.
m:
The mass of the car.
A:
The structural constant of the generator, the voltage per unit speed.
L:
The inductance of the charging circuit.
R:
The resistance of the charging circuit.
C:
The capacitance of the supercapacitor.
alpha:
The dry friction force.
beta:
The viscous friction coefficient.
Returns:
system:
The model, with the speed `car.v`, the current `car.I`, and the capacitor voltage `car.Vs`.
Examples:
>>> from skcomplex.models.engineering.power_systems import regenerative_braking
>>> regenerative_braking(C=100.0).elements[0].C
100.0
"""
car = RegenerativeCarElement('car', v=v, I=0.0, Vs=0.0, m=m, A=A, L=L, R=R, C=C, alpha=alpha, beta=beta)
return System(elements=[car])
Components
class RegenerativeCarElement(Element):
"""Car whose motor recovers braking energy, slowed by dry and viscous friction."""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
v: Annotated[object, StateSpec()] = 20.0,
I: Annotated[object, StateSpec()] = 0.0,
Vs: Annotated[object, StateSpec()] = 0.0,
m: Annotated[object, ParameterSpec(domain=RealSet.open(0, oo))] = 1000.0,
A: Annotated[object, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.2,
L: Annotated[object, ParameterSpec(domain=RealSet.open(0, oo))] = 0.01,
R: Annotated[object, ParameterSpec(domain=RealSet.open(0, oo))] = 0.05,
C: Annotated[object, ParameterSpec(domain=RealSet.open(0, oo))] = 680.0,
alpha: Annotated[object, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 50.0,
beta: Annotated[object, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
) -> None:
super().__init__(label, visual=visual)
self.v = v
self.I = I
self.Vs = Vs
self.m = m
self.A = A
self.L = L
self.R = R
self.C = C
self.alpha = alpha
self.beta = beta
def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
"""Return the rates of the speed, the current, and the charge of the car."""
return [
RateLaw(s.v, -(s.A * s.I + s.alpha * sign(s.v) + s.beta * s.v) / s.m),
RateLaw(s.I, (s.A * s.v - s.R * s.I - s.Vs) / s.L),
RateLaw(s.Vs, s.I / s.C),
]
Equations
car.v: diff(v_car(t), t) == -(A_car*I_car(t) + beta_car*v_car(t) + alpha_car*where(v_car(t) > 0, 1, where(v_car(t) < 0, -1, 0)))/m_car
car.I: diff(I_car(t), t) == -(R_car*I_car(t) - A_car*v_car(t) + Vs_car(t))/L_car
car.Vs: diff(Vs_car(t), t) == I_car(t)/C_car