need recommendation for Symbol and Function

45 views
Skip to first unread message

Thomas Ligon

unread,
Mar 9, 2023, 10:12:46 AM3/9/23
to sympy
I am now using Symbol and Function where the name and the value match. That was recommended for easier reading and then required for pickle. In order to avoid confusing these, I have a different name for Symbol and for Function, then I convert them just before printing. My problem is that I am not sure how to use this when I take derivatives. When I look at q1S in the debugger I see it has type Symbol, but q1F has value q1F(t) and type Q1F (not Function).
The code looks like this:
def createSymbols():
    global t, q1S, q2S, q1F, q2F, q1dotS, q2dotS, q1ddotS, q2ddotS
    t = symbols('t')
    q1S, q2S = symbols('q1S, q2S')
    q1dotS, q2dotS = symbols('q1dotS, q2dotS')
    q1ddotS, q2ddotS = symbols('q1ddotS, q2ddotS')
    q1F = Function('q1F')(t)
    q2F = Function('q2F')(t)
    print('end of createSymbols HillCusp')

def symForLatex(expIn):
    expOut = expIn
    expOut = expOut.subs(q1S, symbols('q1'))
    expOut = expOut.subs(q2S, symbols('q2'))
    expOut = expOut.subs(q1F, symbols('q1'))
    expOut = expOut.subs(q2F, symbols('q2'))
    expOut = expOut.subs(q1dotS, symbols('{\dot{q}}_{1}'))
    expOut = expOut.subs(q2dotS, symbols('{\dot{q}}_{2}'))
    expOut = expOut.subs(q1ddotS, symbols('{\ddot{q}}_{1}'))
    expOut = expOut.subs(q2ddotS, symbols('{\ddot{q}}_{2}'))
    return expOut

Here is the code that calculates higher-order derivatives. The second-order derivative is defined by Newton's equations (ODEs).
    if qi == 1:
        if nDer == 0:
            retVal = q1F#(t)
        elif nDer == 1:
            retVal = diff(qd(1, 0), t)
        elif nDer == 2:
            retVal = 2*qd(2, 1) + 3*qd(1, 0) - qd(1, 0)*(qd(1, 0)**2 + qd(2, 0)**2)**Rational(-3,2)
        else:
            retVal = diff(qd(1, nDer-1), t)
            # replace q1dd & q2dd
            #retVal = retVal.subs(Derivative(q1F(t), (t, 2)), qd(1, 2))
            #retVal = retVal.subs(Derivative(q2F(t), (t, 2)), qd(2, 2))
            retVal = retVal.subs(Derivative(q1F, (t, 2)), qd(1, 2))
            retVal = retVal.subs(Derivative(q2F, (t, 2)), qd(2, 2))


Aaron Meurer

unread,
Mar 9, 2023, 2:59:19 PM3/9/23
to sy...@googlegroups.com
If you want your code to match what is printed, you should write

f = Function('f')

instead of

f = Function('f')(t)

Alternatively you could use a special printer that prints things as
you want. There is already a printer in the mechanics module that
ignores the (t) part when printing a function (mprint()).

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/4f674d25-e795-432e-8ea4-a116005e8dbdn%40googlegroups.com.

Thomas Ligon

unread,
Mar 10, 2023, 11:31:57 AM3/10/23
to sympy
Thanks, but this just shows how poorly I formulated my question. After we solved some printing problems, I am very happy with the way it is working. My problem is Function. With
q1F = Function('q1F')(t)
I get: q1F has value q1F(t) and type Q1F. With
q1F = Function('q1F')
I get nothing, even though this was preceded by
global q1F
I was previously using
q1F = Function('q1F')
and I think it was creating a global q1F with type Function, but I must have broken something.
I am defining both q1S and q1F because I need a symbol for q1 for most calculations, and I also need a function for q1 in order to take derivatives.
        if nDer == 0:
            retVal = q1F#(t)
 returns q1F with no derivative (nDer = number of derivatives), and
        elif nDer == 1:
            retVal = diff(qd(1, 0), t)
 takes the first derivative of the above. (qd(qi=1, nDer) returns the nDer-th derivative of qi=1, i.e. q1).

Thomas Ligon

unread,
Mar 10, 2023, 3:25:29 PM3/10/23
to sympy
I now have a test showing that I can write this either way, and also take the derivative either way. But, it is still irritating not to see q2F in the list of global variables in the debugger. Maybe there is a bug in the debugger. After all I can assign q2F(t) to the variable C, which wouldn't work if it weren't defined. Here is the code:
    global t, q1F, q2F

    t = symbols('t')
    q1F = Function('q1F')(t)
    q2F = Function('q2F')
    #A = q1F(t) # 'q1F' object is not callable
    A = q1F
    print(A) # q1F(t)
    B = diff(A, t)
    print(B) # Derivative(q1F(t), t)
    C = q2F(t)
    print(C) # q2F(t)
    D = diff(C, t)
    print(D) # Derivative(q2F(t), t)


I am using Python inside of Visual Studio and looking for the global variables in the Locals window (with {}Globals expanded). Could someone try this in a different IDE?

Alan Bromborsky

unread,
Mar 10, 2023, 3:34:23 PM3/10/23
to sy...@googlegroups.com

Using geany this is what I see -

Aaron Meurer

unread,
Mar 10, 2023, 3:36:45 PM3/10/23
to sy...@googlegroups.com
My guess is that your debugger is trying to filter classes from the
global variables, since there typically are a lot of them and showing
them doesn't provide a lot of info. Function('f') is actually a class
(same as if you typed "class f(Function): ..."). There's no reason why
global would behave differently for one type of object or another.
Python doesn't care what the type of an object is when it does
scoping.

By the way, personally I would not do this dance with global. If you
want your variables to be defined in the global namespace, just define
them at the module level instead of inside of a function.

Aaron Meurer
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/bafbe3ca-9ef8-4b31-aa7f-548c8512435fn%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages