Use subs to replace subexpression with symbol

27 views
Skip to first unread message

arne-ws

unread,
Sep 15, 2014, 5:31:07 AM9/15/14
to sy...@googlegroups.com
I'm trying to replace a nested function with a symbol by applying subs.

However, this doesn't seem to work for every case:
For Equation (2) my code below prints what I expect:

D_star = 

C_vss
D_th
──────────
  C_vth  

But for Equation (3) subs doesn't seem to work and f_v is printed rather longish as:

f_v = 

     
                                      3/2              
     
                   _________    ⎞⎞                  
     
                   φ          ⎟⎟                  
     
        C_tD_th⋅⎜    ─── + 1  - 1⎟⎟               3/2
     
                ⎝╲╱   φ_t         ⎠⎟          ___  
     
    -k₁⋅⎜────────────────────────────⎟   ⋅⎝1 + ╲╱ 2  
     
                 C_vth⋅φ                            
f_max
⋅⎝1 -                                                    


Any idea why subs is not working for Equation (3)?
Thanks!
Arne


Code example:
import sympy as sp
s = sp.Symbol 
print 'sympy version ' + sp.__version__ + '\n'

def s_print(func_str, repl_str=None):
    '''Print function and replace subexpression'''
    print func_str + ' = \n'
    if repl_str != None:
        sp.pprint(eval(func_str).subs(eval(repl_str), s(repl_str)))
    else:
        sp.pprint(eval(func_str))
    print '\n'

# (1) C_vss
phi, phi_t, C_t = sp.symbols('phi phi_t C_t')
C_vss = (sp.sqrt(2) + 1)*C_t*(sp.sqrt(1 + phi/phi_t) - 1)
s_print('C_vss')

# (2) D_star
C_vth, D_th = sp.symbols('C_vth D_th')
D_star = C_vss/C_vth * D_th
s_print('D_star', 'C_vss')


# (3) f_v
f_max, k_1, Phi = sp.symbols('f_max k_1, Phi')
f_v = f_max * (1 - sp.exp(-k_1 * (D_star/phi)**(sp.Rational(3,2))))
s_print('f_v', 'D_star')


Chris Smith

unread,
Sep 15, 2014, 10:47:44 AM9/15/14
to sy...@googlegroups.com
Let's see where the problem is:

>>> arg=(1+sqrt(2))*x
>>> arg.subs(arg,1)
1

That was ok (and easy). Now let's wrap it in sqrt

>>> sqrt(arg).subs(arg,1)
sqrt(x)*sqrt(1 + sqrt(2))

That time there was no change -- it doesn't see a single "arg" when the powers are split.

>>> (sqrt(arg)**3).subs(arg,1)
sqrt(x)*sqrt(1 + sqrt(2))

Hmmm...but this time it got 1 of the 3/2 replaced

>>> (sqrt(arg/y)**3).subs(arg/y,1)
(x/y)**(3/2)*(1 + sqrt(2))**(3/2)

But none of a more complicated arg is replaced.

>>> (sqrt(arg/y)**3).subs(sqrt(arg/y),2)
8

If you match the fractional part of the power it looks like it can do it. But if I try s_print('f_v','sqrt(D_star)') this doesn't work.

Looks like a bug.
Reply all
Reply to author
Forward
0 new messages