New version 0.34 and "kneechord" strategy
Telford Tendys <[email protected]>
| Newsgroups | gmane.comp.gnu.gnucap.devel |
|---|---|
| Message-ID | <20040307172536.B16420@ikkyu> |
Good to see a new version of gnucap out... I couldn't help noticing that my kneechord code has been merged with the core to some extent but for anyone who wants to use it they will have to add a -DKNEECHORD to the Makefile and also add inverse.cc and inverse.o to the list of sources and objects respectively. I found a few issues with the current kneechord strategy as installed in gnucap 0.34. In a nutshell, the problem is that the strategy only makes sense for non-linear components. It is useless to call it for completely linear components (although the knee_chord() detects perfectly linear components within a few iterations and drops out quickly) and it's a big waste of calculating cycles to call it for a constant. Consider the case of an ordinary current source connected to the generator() function. Because this is an element, it will be subject to the kneechord strategy and because of the generator, it will attempt to call the tr_eval(). The problem here is that the generator provides a time dependent function which is a fixed output (not dependent on any other variables in the network) so with regards to converging the matrix equations this element is really just a constant. But the knee_chord() doesn't understand that it has been handed a constant so it tries to find the inverse function (and fails with a warning). This is not actually harmful, but it is counterproductive because it keeps trying for 200 evaluations until it decides that there is no inverse function. What is really needed is some meta-data available for the tr_eval() function call. Thanks to the magic of g++ and inheritance, the tr_eval() has become all things to all elements throughout the simulator. That's fine from the point of view of getting values for elements but I can't find a way for the knee_chord() function to detect whether the tr_eval() it gets is going to be a nonlinear function dependent on the element x or a time dependent constant or some other such thing. The only way to find out what tr_eval() does is to send in some values and see what comes back. My suggestion is that has_tr_eval() should not return boolean but return an unsigned 32 bit number that contains useful flags like: * Does it depend on time ? * Does it depend on local element x ? * Is it non-linear ? And probably a few other things like whether the first derivative is available (current presumption is yes but that may not always be true). Possibly also some indication of how expensive a call to tr_eval() is likely to be. If is necessary to keep has_tr_eval() boolean then some other inheritable meta-data mechanism would be useful. I'm not sure how many other non-linear coping strategies are likely to be employed; the secant strategy is probably safe to employ on everything, more complex algorithms (like kneechord) are only beneficial on some element functions. This also makes me think about whether it would be good to be able to select a strategy on an element by element basis. Admittedly, the ideal would be automatic strategy selection but allowing user override is always a good idea and just supporting the concept of element by element strategy might be a first step towards auto-selection. Aside from the above, if anyone is trying to model nonlinear inductors (e.g. saturating cores in snubber networks) then I'd be curious to hear from them. I don't mind giving a hand with a few suggestions if anyone is having trouble. I'm also curious if anyone has tried kneechord on saturating semiconductor models. It should be good for that but I haven't tried it myself, if anyone is having convergence problems with such models then it might be worth a try. - Tel