This probably should be a bug ticket, but I don't have permission to create one.
The manual says that is like pwr() and that pow() is x to the power y, while pwr(x,y) is abs(x) to the power y.
The way they actually work is that pow(x,y) is abs(x) to the power y, while pwr(x) is sign(x) time pow(x,y). And there isn't an actual x to the power y function; I have to use pow() for even y and pwr() for odd y, which is strange.
This is ngspice 0.29.
The page you refer to talks about PSPICE compatibility mode. I'm not using that. In default mode, "pwrs" does not exist.
Attached is a small test program. It shows that the star-star operator is the same as the "pow" function -- and that function always returns a positive result (it raises abs(x) to the power y). The test also shows that pwr(x,y) returns pow(x,y) times sign(x).
So if I want the mathematically correct power operation, I have to use pow(x,y) for odd y, and pwr(x,y) for even y. Meanwhile, none of these operations match the "pow" function in the C library, which does the mathematically expected thing.
In short, there are two issues: (a) the manual is wrong about "pow", and (b) while it correctly describes the star-start operator as equivalent to "pwr", that definition is a very bad choice because the operator has a standard meaning which is the mathematical power operation, without the absolute value thing. If this surprising behavior really is needed, it should at least be warned about.
As Marcel already said, we have three different sections in ngspice using functions. These functions are defined in different source code areas. I have tried to figure out what we have in detail:
a) Parametric functions (e.g. used in .param statements). These are described in chapter 2.8 of the manual. Here you have
**
,^
,pow
, andpwr
. These functions are evaluated before the simulation has started, i.e. during parsing the circuit.Source code is in src\frontend\numparam\xpressn.c. We have
and (
**
is reduced to^
)b) Functions to be used in the B source and behavioral descriptions of device elements. These are listed in chapt. 5.1.1.
pow
and^
are mentioned there (not really described). These functions are evaluated during the simulation. Thus they may act on node voltages or branch currents.The source code is to be found in src/spicelib/parser/inpptree.c (setting up the parse tree) and ptfuncs.c (evaluate the functions). There we have also the
pwr
function, not mentioned in the manual and**
is reduced to^
. inpptree.c contains detailed descriptions of the functions and their derivatives.pow
and^
are the same (function PTpower),pwr
is different (function PTpwr).c) Functions available in the interactive interpreter (control language, some call these nutmeg equations). Their description is available in chapt. 17.2. There is no mentioning of power functions. These functions may be used to evaluate simulation results, they act on (output) vectors and are invoked only after the simulation (or during the simulation being interrupted).
Source code is in src/frontend/evaluate.c and src/maths/cmaths/cmath3.c.
In addition you may define your own functions, either using the
.func
statement from the param section (chapt. 2.9) or using thedefine
command of the control language (chapt. 17.5.15).Last edit: Holger Vogt 2018-12-29
Ouch. So we have the same function name with different semantics depending on where it appears. That's very nasty, and not at all clear from the manual. The impression I got from the manual talking about the three parsers is that they have subtle differences in how parentheses are written or whether they can handle spaces. There wasn't anything that suggested that the same expression might have utterly different -- and very surprising -- semantics.
On 2018-12-29 19:00, Paul Koning wrote:
True. It would certainly be a good idea to carefully update the
manual on this.
I suspect there are sound practical engineering reasons for the
behavior. It is obvious that a strict mathematical power function
will create issues for the mix of functions that SPICE almost
exclusively encounters: polynomials, square roots, and logarithms.
(Imagine the non-linear solver tries to find a root, and the
Newton-Raphson iterates inwards around zero and needs to evaluate
negative possibilities. Your example shows the classical situation
where the solver will diverge, even if sqrt(-1) were
correctly handled :-).
It certainly is tempting to revert to the mathematical power function
and have the users and model authors solve the issues on a
case-by-case basis. This would, however, invalidate almost
all existing SPICE decks (and models, and sub-circuits). Also,
it might be that the existing implementation mostly does what
one needs to do in the end anyway.
-marcel
I can see the point. But it was a nasty surprise when I was building a non-linear device model (of a carbon microphone). Fitted a polynomial to it with gnuplot, and was trying to figure out why that same polynomial with the same coefficients didn't reproduce the correct waveform in ngSPICE. Once I puzzled out the undocumented weirdness I got it to work as expected.