Re: New version 0.34 and "kneechord" strategy
Al Davis <[email protected]>
| Newsgroups | gmane.comp.gnu.gnucap.devel |
|---|---|
| Message-ID | <[email protected]> |
Sorry about the slow response. The list server has been very slow lately. On Sunday 07 March 2004 01:25 am, Telford Tendys wrote: > 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 started on it, then had other things get in the way of finishing it. By including it this way, people wanting to get involved can try work in progress, but people who just want to use it are not exposed to the extra risk of experimental code. Some other experimental code is compiled in and available through undocumented options. > 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. It is not called for purely linear components. Actually, even "do_tr" is not called for purely linear components, except in rare circumstances. Because of these rare circumstances, it must work. The separation isn't perfect, as you say later. > 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. Maybe a fixed number of iterations here is not a good idea, but these things happen in experimental code. A similar situation could exist for a nonlinear component operating in a linear region, where no iterations take it outside. > 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 ? That violates encapsulation, so it will not change. "has_tr_eval" tells you whether the element has a tr_eval. Nothing else. There are other query methods that give different information. The way to handle this is to add other query methods "depends_on_time()", "depends_on_x()", "is_nonlinear()", etc. as needed. These would all be inline const methods returning bool. > And probably a few other things like whether the first derivative > is available (current presumption is yes but that may not always > be true). Not only that... Even if the answer is "no", it is the responsibility of tr_eval to supply one. This strategy is used throughout. a few examples ... Even if there is no tr_eval(), it is ok to call element->tr_eval(), and the fake must give the illusion of the real thing. The output of a logic device is a logic state. The voltage doesn't exist. Perhaps the node doesn't exist. If there are analog components hooked there, it will fake it. > Possibly also some indication of how expensive a call to > tr_eval() is likely to be. That is easy to do. Add a method "tr_eval_cost()", that returns some constant. How about the number of lines of code in tr_eval()? That will be needed as part of cached model evaluation, to make the decision of how much to cache. It would belong to the common. Calling common->tr_eval() would get the real function. Calling element->tr_eval() might fake it by giving you a cached value. > If is necessary to keep has_tr_eval() boolean then some other > inheritable meta-data mechanism would be useful. You need to stop thinking C. :-) > 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. secant, false position, relaxation, bisection, various homotopy methods, steepest descent minimization, harmonic balance, AWE, krylov subspace methods, ...... > 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. Eventually, that is the intent. > 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. The current implementation doesn't work on semiconductor models, because they are multi-variable. Calling it from ELEMENT::tr_eval only works for elements that have a simple "x". The multi-variable elements are where the help is needed most.