Yotam Ohad
Yotam Ohad

Reputation: 322

Use `sympy.Order` with functions, instead of symbols

I have a problem like this f(u(x,y), v(x,y)) = 0. For a simple example we could choose f=u^2*v. I want to perturb the state with u=u_0+du,v=v_0+dv. Just doing it in sympy like:

import sympy as sp
x, y = sp.symbols("x, y")
u0, v0 = sp.symbols("u_0, v_0")

du = sp.Function("\\delta u")(x, y)
dv = sp.Function("\\delta v")(x, y)

u = u0 + du
v = v0 + dv

f = u**2 * v
print(sp.expand(u**2 * v))

I get u_0**2*v_0 + u_0**2*\delta v(x, y) + 2*u_0*v_0*\delta u(x, y) + 2*u_0*\delta u(x, y)*\delta v(x, y) + v_0*\delta u(x, y)**2 + \delta u(x, y)**2*\delta v(x, y)

Is there a way to tell sympy that any product of deltas can be zero? I tried using sp.Order but it doesn't work where the series is a power of some function

Thanks

Upvotes: 0

Views: 46

Answers (1)

smichr
smichr

Reputation: 19077

I usually approach these tasks from an expression manipulation point of view: knowing what I am looking for I seek to make that change (as opposed to letting something like series do what it should do). In this case you are looking for terms that have a product of functions. Such terms could be a Power (like f**2) or a Mul (like x*f1*f2). So something like this could be done:

def funcpow(x):
    rv = 0
    if x.is_Mul or x.is_Pow:
        for i in Mul.make_args(x):
            b,e=i.as_base_exp()
            if b.is_Function:
                rv += e
    return rv

>>> eq.replace(lambda x: funcpow(x)>1, lambda x: 0)
u_0**2*v_0 + u_0**2*\\delta v(x, y) + 2*u_0*v_0*\\delta u(x, y)

Often, the conditions are placed in the call to replace but since there are several I made a helper function instead.

Upvotes: 1

Related Questions