Menu

#33 pwr() and pow() and ** issue

v1.0 (example)
open
nobody
None
5
2018-12-29
2018-12-28
Paul Koning
No

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.

Related

Support Requests: #33

Discussion

  • Paul Koning

    Paul Koning - 2018-12-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.

     
  • Holger Vogt

    Holger Vogt - 2018-12-29

    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, and pwr. 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

        case XFU_POW:
            y = pow(z, x);
            break;
        case XFU_PWR:
            y = pow(fabs(z), x);
            break;
    

    and (** is reduced to ^)

        case '^':                   /* power */
            x = pow(fabs(x), y);
            break;        
    

    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).

    double
    PTpower(double arg1, double arg2)
    {
        return pow(fabs(arg1), arg2);
    }
    
    double
    PTpwr(double arg1, double arg2)
    {
        /* if PSPICE device is evaluated */
        if (arg1 == 0.0 && arg2 < 0.0 &&
            (inp_compat_mode == COMPATMODE_PS || inp_compat_mode == COMPATMODE_PSA
            || inp_compat_mode == COMPATMODE_LTPS || inp_compat_mode == COMPATMODE_LTPSA))
            arg1 += PTfudge_factor;
    
        if (arg1 < 0.0)
            return (-pow(-arg1, arg2));
        else
            return (pow(arg1, arg2));
    }
    

    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 the define command of the control language (chapt. 17.5.15).

     

    Last edit: Holger Vogt 2018-12-29
  • Paul Koning

    Paul Koning - 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.

     
    • marcel hendrix

      marcel hendrix - 2018-12-29

      On 2018-12-29 19:00, Paul Koning wrote:

      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.

      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

       
  • Paul Koning

    Paul Koning - 2018-12-29

    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.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.