Qucs / gnucsator

This package provides a gnucap based qucsator implementation.
GNU General Public License v3.0
13 stars 4 forks source link

A different timestep issue #10

Closed ddrake closed 3 years ago

ddrake commented 3 years ago

Transient simulation of this common emitter amplifier circuit (see attached netlist) fails using gnucsator (current develop) if the amplitude U of the sinusoidal voltage input signal is >= 0.888V.

gnucsator: s_tr_swp.cc:292: bool TRANSIENT::next(): Assertion `new_dt >= _sim->_dtmin' failed.

If the amplitude U <= 0.887V, it has no issues and the number of timesteps and iterations seems reasonable. For example, with U = 0.887V we get:

Gnucap   System status
iterations: op=0, dc=0, tran=2286, fourier=0, total=2788
transient timesteps: accepted=502, rejected=0, total=502
transient timesteps: accepted=0, rejected=0, total=0
nodes: user=5, subckt=0, model=1, total=6
dctran density=83.3%, ac density=83.3%

This circuit is simulated correctly by qucsator for all input amplitudes. Noticeable clipping of the bottom of the output signal begins to occur for input amplitudes > 0.9V. This may relate to the gnucsator issue above.

netlist.txt

Edit: In case it might be helpful, here's a plot generated by qucsator for U = 0.95 (the clipping is visible at the bottom).

export

felix-salfelder commented 3 years ago

On Sat, Sep 25, 2021 at 05:15:38PM -0700, Dow Drake wrote:

Transient simulation of this common emitter amplifier circuit (see attached netlist) fails using gnucsator (current develop) if the amplitude U of the sinusoidal voltage input signal is >= 0.888V.

gnucsator: s_tr_swp.cc:292: bool TRANSIENT::next(): Assertion `new_dt >= _sim->_dtmin' failed.

If the amplitude U <= 0.887V, it has no issues and the number of timesteps and iterations seems reasonable. For example, with U = 0.887V we get:

Gnucap   System status
iterations: op=0, dc=0, tran=2286, fourier=0, total=2788
transient timesteps: accepted=502, rejected=0, total=502
transient timesteps: accepted=0, rejected=0, total=0
nodes: user=5, subckt=0, model=1, total=6
dctran density=83.3%, ac density=83.3%

This circuit is simulated correctly by qucsator for all input amplitudes. Noticeable clipping of the bottom of the output signal begins to occur for input amplitudes > 0.9V. This may relate to the gnucsator issue above.

This is fixed in gnucsator/develop. The zero area pnp has caused some trouble. It does no longer do that when shutting down all subdevices (which is what I should have done anyway).

I don't know how exactly s_tr_swp.cc:292 got triggered (note that we use an old version.), but it does not seem to require further action. It only happened with tstep=tend/500.

NB1: Al suggested to add a polarity parameter in bjt, and then drop the mirror device from the wrapper. This may be more correct, as far as introducing extra instance parameters is correct. But it involves extra work -- i'll leave it like it is until some other issue shows up.

NB2: Possibly same issue with the FETs.

ddrake commented 3 years ago

Great -- I tested just now. I had a few other circuits with similar issues; they're all working correctly now. I'll have a look at your commit to try to get a better understanding.

NB2: Possibly same issue with the FETs.

I'm still working through Horowitz & Hill chapter 2, but will definitely be running tests with FETs once I make it to chapter 3. I'll let you know...

felix-salfelder commented 3 years ago

gnucsator: ": bool TRANSIENT::next(): Assertion `new_dt >= _sim->_dtmin' failed.

A failed assert always indicates a "bug". There is something wrong with the program that needs attention. "The program" here considers plugins, even if user supplied, to be part of "the program". There may be also user errors, but that is of minor significance in this case. Assert messages are designed to be developer friendly, not user friendly. You need to look at it with a debugger. (gdb)

The "options" are not arbitrary numbers. The default values for the options are usually reasonable. Changing them usually results in worse performance, but that depends on what you are doing.

In this case, "_sim->_dtmin" is the value of the option "dtmin". "Minimum time step. The smallest internal time step in transient analysis." The default value is 1e-12 ... one picosecond. Unless you care about time accuracy to better than one picosecond, the default value is probably ok. Making the number smaller (1e-18??) will probably make things worse because of numerical noise. Making it larger will probably make no difference, unless you make it so much larger that it reduces accuracy by masking the results you want to see.

Gnucap time stepping is based on absolute time. DT (the size of the time step) is a derived parameter. This is the opposite of Spice, which considers the step size first and absolute time to be the derived parameter by repeatedly adding DT.

So the meaning of "dtmin" is that if I have two times, t1 and t2, the difference cannot be resolved if they are closer than dtmin, so are considered to be the same time, simultaneous.

Where this failed assert came from "s_tr_swp.cc:292" is in a plugin (s_tr*.cc, the transient command), in the function next(), which has the simple purpose of setting the time for the next step, as _sim->_time0 , and as side effects stash the old time as _sim->_time1 and to stop if the time is up.

It examines info from around to determine the time, taking the most distant first, then moving it in. The meaning of the message is that there is a request for the new time ("newtime") at essentially the same time as the old time ("reftime"), even though the old time has already been accepted as correct and accurate.

So who asked for that time, and why?

Get the debugger "gdb". Run gnucap in the debugger, until it crashes with that assert. Look at the stack ("bt"), get up to the spot the assert failure happened. (rather than the assert handler which is the code that printed the message). Get the source file, see line 292, and look at how it got there.

At this point in the code, line 292, not much has been done. Look at new_control, newtime, reftime, ... to find out what is going on.

I don't know how exactly s_tr_swp.cc:292 got triggered (note that we use an old version.), but it does not seem to require further action. It only happened with tstep=tend/500.

Actually, it does require further action.

In gnucap, it is almost always best to not specify a time step, and let the automatic step control determine it.

If you do specify a time step, it is considered to be a strobe. If you do not ask for "trace all" it will hide the steps you didn't request. This is intended for primitive post-processing software or text plots, that may require fixed time steps. The syntax is intended to be Spice-2 compatible, that is the old Fortran version of Spice, and dates back to those days, when ASCII text plots were all you could get.

Since the step is interpreted as a strobe, some detail is suppressed, so a plot may show straight line interpolation between samples, which may look incorrect but really isn't.

For this circuit, probably 500 time steps is way too many. If you just let it run as designed, the automatic stepping will do small steps at the corners to meet the accuracy spec and much larger steps in between when nothing is happening.

If you are seeing flat line segments in the plot when you expect a smooth curve, I recommend improving the plotter. By default, gnucap time stepping is based on cubic splines. You can change this by the option "trsteporder", which has the default value of 3, as in cubic. If you change it to 1 (linear), gnucap will do extra steps to make for a better plot on simple plotters that use linear (order=1) interpolation.

When simulators, Spice derivatives or not, specify "Spice compatibility", they go back to roots of either Spice-2 (Fortran) or Spice-3 (C). They tend to be in one category or the other. As I understand, Gnucap, Hspice, Pspice are in the "Spice-2" group, and NGspice, ISspice, and most others are in the "Spice-3" group.

felix-salfelder commented 3 years ago

On Fri, Oct 01, 2021 at 08:20:40PM -0400, al davis wrote:

If you are seeing flat line segments in the plot when you expect a smooth curve, I recommend improving the plotter. By default, gnucap time stepping is based on cubic splines. You can change this by the option "trsteporder", which has the default value of 3, as in cubic. If you change it to 1 (linear), gnucap will do extra steps to make for a better plot on simple plotters that use linear (order=1) interpolation.

Thanks, this is what I was looking for. There are now three bjt_pulse tests, bjt_pulse{0,1,2}.net. The unmodified produces 16 data points, adding a switch gives 20. With trsteporder=1 one gets 112, most likely what a Qucs user would like to see.

Any of the above seems better than using the Points parameter. I wonder if trsteporder=1 makes a good default setting in Gnucsator. For now, please see gnucsator.rc, and customise.

felix-salfelder commented 3 years ago

On Fri, Oct 01, 2021 at 08:20:40PM -0400, al davis wrote:

I don't know how exactly s_tr_swp.cc:292 got triggered (note that we use an old version.), but it does not seem to require further action. It only happened with tstep=tend/500.

Actually, it does require further action.

Perhaps I wasn't clear about the context. Please read: It only happened with tend/500 and the broken models in gnucsator including the unpatched bjt with area=0. There is no evidence for a problem with s_tr_swp.cc.

In the meantime I have also fixed the use of the Qucs MOSFET, it has a polarity "parameter" similar to BJT. The mos model does not have an area parameter, and I once tried w (it doesn't work). But mfactor=0 works everywhere I tried:

mynmos #(.w(W), .m((1.+Type).5), .l(L), .temp(Temp)) n(d, g, s, b); mypmos #(.w(W), .m((1.-Type).5), .l(L), .temp(Temp)) p(d, g, s, b);

In my understanding, mfactor simply scales all conductance and current contributions, here selecting the polarity following Qucs conventions. Also, evaluation and time step control in the mos model seem to be sufficiently forgiving about reverse voltages.

In principle, and generally, devices with mfactor=0 could be taken out of the equation with more rigour. I expect more model selection and "multiview" demands down the line -- patching or extending every single model is not practical.

For example: load some_spice/d_bjt.so breaks BJT in Gnucsator. This is bad, because (pug and play) using foreign models is useful. What are the options?