@staticmethod
def kinetic_model(z, t, *kinetic_constants):
    """
        Return change of yeast, ethanol, and substrate concentration in kg/m3.
        
        Parameters
        ----------
        z : Iterable with (X, E, S) [-]:
            * X: Yeast concentration (kg/m3)
            * P: Ethanol concentration (kg/m3)
            * S: Substrate concentration (kg/m3)
        
        t : float
            Time point
        
        *kinetic_constants
            * mu_m1: Maximum specific growth rate (1/hr)
            * mu_m2: Maximum specific ethanol production rate (g-product/g-cell-hr)
            * Ks1: Sugar saturation constant for growth (g/L)
            * Ks2: Sugar saturation constant for product (g/L)
            * Pm1: Maximum product concentration at zero growth [mu_m1=0] (g/L)
            * Pm2: Maximum product concentration [mu_m2=0] (g/L)
            * Xm: Maximum cell concentration [mu_m1=0] (g/L)
            * Y_PS: Ethanol yield based on sugar consumed
            * a: Toxic power
                
        """
    mu_m1, mu_m2, Ks1, Ks2, Pm1, Pm2, Xm, Y_PS, a = kinetic_constants
    X, P, S = z
    mu_X = mu_m1 * (S / (Ks1 + S)) * (1 - P / Pm1) ** a * (1 - X / Xm)
    mu_P = mu_m2 * (S / (Ks2 + S)) * (1 - P / Pm2)
    mu_S = mu_P / 0.45
    dXdt = mu_X * X
    dPdt = mu_P * X
    dSdt = -mu_S * X
    return dXdt, dPdt, dSdt
