Skip to content

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