简体   繁体   中英

Differential equation change of variables with sympy

I have an ordinary differential equation like this:

DiffEq = Eq(-ℏ*ℏ*diff(Ψ,x,2)/(2*m) + m*w*w*(x*x)*Ψ/2 - E*Ψ   ,  0)

Use the following function:

def variable_change(ODE,dependent_var, 
                    independent_var,
                    new_dependent_var = None, 
                    new_independent_var= None, 


                    dependent_var_relation = None,
                    independent_var_relation = None,
                    order = 2):





    if new_dependent_var == None:
        new_dependent_var = dependent_var
    if new_independent_var == None:
        new_independent_var = independent_var




    # dependent variable change

    if new_independent_var != independent_var:

        for i in range(order, -1, -1):

            # remplace derivate
            a = D(dependent_var , independent_var, i )
            ξ = Function("ξ")(independent_var)

            b = D( dependent_var.subs(independent_var, ξ),  independent_var  ,i)

            rel = solve(independent_var_relation, new_independent_var)[0]


            for j in range(order, 0, -1):
                b = b.subs( D(ξ,independent_var,j), D(rel,independent_var,j))

            b = b.subs(ξ, new_independent_var)

            rel = solve(independent_var_relation, independent_var)[0]
            b = b.subs(independent_var, rel)


            ODE =   ODE.subs(a,b)

        ODE = ODE.subs(independent_var, rel)


    # change of variables of indpendent variable


    if new_dependent_var != dependent_var:

        ODE = (ODE.subs(dependent_var.subs(independent_var,new_independent_var) , (solve(dependent_var_relation, dependent_var)[0])))
        ODE = ODE.doit().expand()

    return ODE.simplify()

For the example posted:

from sympy import *
from sympy import diff as D

E, ℏ ,w,m,x,u = symbols("E, ℏ , w,m,x,u")
Ψ ,H = map(Function, ["Ψ ","H"])
Ψ ,H = Ψ(x), H(u)



DiffEq = Eq(-ℏ*ℏ*D(Ψ,x,2)/(2*m) + m*w*w*(x*x)*Ψ/2 - E*Ψ,0)
display(DiffEq)



display(Eq(u , x*sqrt(m*w/ℏ)))
display(Eq(Ψ, H*exp(-u*u/2)))


newODE = variable_change(ODE = DiffEq,


                independent_var = x, 
                new_independent_var= u,
                independent_var_relation = Eq(u , x*sqrt(m*w/ℏ)),
                dependent_var = Ψ,  


                new_dependent_var = H,   
                dependent_var_relation = Eq(Ψ, H*exp(-u*u/2)),

                order = 2)







display(newODE)

Under this substitution the differential equation outputted is then:

Eq((-E*H + u*w*ℏ*D(H, u) + w*ℏ*H/2 - w*ℏ*D(H, (u, 2))/2)*exp(-u**2/2), 0)

If anyone is wondering how they could do it as well on CoCalc notebooks/anywhere where you can mix Sage and Python, here I defined basically the same variables and functions as OP did, and then after substitution the result is converted back to Sage:

var("E w m x u")
var("h_bar", latex_name = r'\hbar')
Ψ = function("Ψ")(x)
H = function('H')(u)

display(h_bar*diff(Ψ, x, 2))
DiffEq = (-h_bar*h_bar*Ψ.diff(x, 2)/(2*m) + m*w*w*(x*x)*Ψ/2 - E*Ψ == 0)
display(DiffEq)

display(u == x*sqrt(m*w/h_bar))
display(Ψ == H*exp(-u*u/2))


newODE = variable_change(
    ODE = DiffEq._sympy_(),
    independent_var = x._sympy_(),
    new_independent_var = u._sympy_(),
    independent_var_relation = (u == x*sqrt(m*w/h_bar))._sympy_(),
    dependent_var = Ψ._sympy_(),
    new_dependent_var = H._sympy_(),
    dependent_var_relation = (Ψ == H*exp(-u*u/2))._sympy_(),
    order = 2
)

display(newODE._sage_())

Note that the only difference is that here things are converted to SymPy when using as arguments inside OP's function (it'll probably break if you don't!). After you call _sympy_() only once on a variable of expression, every sympy object gets a _sage_() method to convert back .

The result given was:

1/2*(2*h_bar*u*w*diff(H(u), u) + h_bar*w*H(u) - h_bar*w*diff(H(u), u, u) - 2*E*H(u))*e^(-1/2*u^2) == 0

Which is just OP's result, but Sage handles operands a little bit differently.

Note: in order to avoid overriding stuff on Sage after importing everything from SymPy, you may want to import only diff as D , Function and solve from the main library. You might also want to rename sympy's solve to something else to avoid overriding Sage's own sage.symbolic.relation.solve .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM