On 20.06.2014, at 11:11, Tim Goetze <t...@quitte.de> wrote:

>  I
> mistakenly thought you were proposing nodal analysis including also
> the nonlinear aspects of the circuit including valves and output
> transformer (which without being too familiar with the method I
> believe to lead to a system of equations that's a lot more complicated
> to solve).

Well, it might not be as straight forward, but there are various methods to 
solve non-linear systems of equations.

The main problem arises when a non-linear element occurrs on both sides of an 
equation, such as

Vout = g * ( tanh( Vin ) - tanh( Vout ) ) + iceq

As one can't solve this for Vout, there's a few different approaches to deal 
with it computationally.

The most common one is to introduce a unit delay (aka the "naive method")

Vout[ n ] = g * ( tanh( Vin[ n ] ) - tanh( Vout[ n - 1 ] ) ) + iceq

This however leads to mangled phase/frequency response and worse time invariant 
properties, e.g. when sweeping g

A quick and easy method to resolve this is to only apply the unit delay to the 
effect of the non-linearity itself, but keep the system delay-less for its 
linear components:

Vout = g * ( tanh( Vin ) - f[ n-1 ] * Vout  ) + iceq
f[ n ] = tanh( Vout )/Vout;

This way the equation can be solved for Vout and the non-linearity becomes a 
factor that's applied with one sample delay.

Similar methods apply an offset and a tangent to linearize the non-linearity 
for a moment in time.

So far this is computationally easy going, but it's also a compromise in 
accuracy. To become numerically accurate one typically uses iterative methods 
to "look into the future". A very simple approach is to estimate the value in 
question, calculate the equation and compare the estimate with the result. From 
there on one can refine the estimate until it converges with the result in any 
desired accuracy, such as

while ( abs( Vout_result - Vout_estimate ) > 0.0001 )
{
    Vout_estimate = rootFindingAlgorithmOfChoice( Vout_result );
    Vout_result = g * ( tanh( Vin ) - tanh( Vout_estimate ) ) + iceq
}

There you go. It's very basic and it can be optimised to run on a modern CPU.

Cheers,

- Urs

--
dupswapdrop -- the music-dsp mailing list and website:
subscription info, FAQ, source code archive, list archive, book reviews, dsp 
links
http://music.columbia.edu/cmc/music-dsp
http://music.columbia.edu/mailman/listinfo/music-dsp

Reply via email to