The model that I have used for the triode, for negative grid voltages, has come from the following paper,
Measures and parameter estimation of triodes, for the real-time simulation of a multi-stage guitar preamplifier, Ivan Cohen, and Thomas Helie, Audio Engineering Society, Convention Paper, Presented at the 129th Convention 2010 November 4–7 San Francisco, CA, USA
To fit the model a set of measured values for the anode voltage and anode current, for given grid voltages, is required. It is then possible to derive the six model parameters {u, Ex, Kg, Kp, Kvb, Vct} using curve fitting and optimisation tools.
The curve fitting tool that I use is the optmize.curve_fit() function from the Python SciPy library, using the following Python code,
params, params_covariance = optimize.curve_fit(koren, x_data, y_data, method='trf',
bounds=((1,-np.inf,-np.inf,-np.inf,-np.inf,-np.inf),(np.inf, np.inf, np.inf, np.inf, np.inf, np.inf)))
The curve_fit function takes the following arguments,
The reference to the function that implements the triode model which has arguments for the measured data (Vanode-cathode, Vgrid_cathode), and the six model parameters that need to be found {u, Ex, Kg, Kp, Kvb, Vct} , and returns the model calculated value for anode current. (See Python function definition below)
The measured data for the model input data (Vanode-cathode, Vgrid_cathode)
The measured data fro the Anode current
The optimisation method to be used, and I have found that the 'trf' method works best, especially where there are constraints on the parameter values.
The bounds, or constraints, for the model parameters, where I have found it helps to constraint the u parameter to be >=1.
def koren(x, u, Ex, Kg, Kp, Kvb, Vct): # x[0] = Vgrid_cathode, x[1] = Vanode_cathode
Vpk = x[1]
Vgk = x[0]
E1 = (Vpk / Kp) * np.log(1 + np.exp(Kp * ((1 / u) + (Vgk + Vct) / np.sqrt(Kvb + Vpk * Vpk))))
E1 = abs(E1) #np.exp cannot handle negative number (E1) to fractional powers
Ip = 2 * np.power(E1, Ex) / Kg
return Ip