(Some function) is not defined with SymPy Lambdify - python

So I'm writing a script that evaluates Taylor Series. However, I want it to evaluate for all types of functions. So I tried, for example, using the function acot(x).
x = sy.Symbol('x')
f = acot(x)
...
func = taylor(f,0,3)
taylor_lambda = sy.lambdify(x, func, 'numpy')
The above runs without an exception (except if I use acsch, for example, and it does not run).
But then when it reaches this line:
plt.plot(x1,taylor_lambda(x1),label='taylor approximation')
I get:
NameError: name 'acot' is not defined
I tried to replace numpy with sympy in the lambdify call but this seems to evaluate symbolically. This is happening with some (more rare functions) but not for others. Thank you!
My imports are as follows:
import sympy as sy
import numpy as np
from sympy.functions import *
from sympy import pi, E,acot
import matplotlib.pyplot as plt
import math

The main issue here is that the lambdify function uses the modules argument to define available modules for the supplied function. It seems acot is not available within the numpy namespace.
Lets reduce this down to something simple:
import sympy as sy
import numpy as np
from sympy.functions import *
x = sy.Symbol('x')
f = acot(x)
func_lambda = sy.lambdify(x, f, modules='numpy')
print(func_lambda(1))
This raises a NameError as acot is not defined in the numpy namespace. Note the modules argument. If we extend the available modules to sympy, we no longer get a NameError:
func_lambda = sy.lambdify(x, f, modules=['numpy', 'sympy'])
print(func_lambda(1))
# Prints pi/4
If you're having trouble with odd functions, you can also add individual functions to the lambdify modules parameter as a dictionary of func_name: function pairs:
func_lambda = sy.lambdify(x, f, modules=['numpy', {'acot':acot}])
print(func_lambda(1))
# Prints pi/4
As far as plotting using matplotlib, vectorizing the equation and then plotting works for me:
import matplotlib.pyplot as plt
vfunc = np.vectorize(func_lambda)
x1 = np.linspace(-10, 10 , 1000)
plt.plot(x1, vfunc(x1),label='acot')
plt.show()

I did have similar problems before and have managed to solve them.Your line
plt.plot(x1,taylor_lambda(x1),label='taylor approximation')
looks OK.I am giving one my older code that works fine,you can just compare.
from sympy.abc import x
from sympy import sin, series
from sympy.utilities.lambdify import lambdify
import numpy as np
import matplotlib.pyplot as plt
func = sin(x)/x
taylor = series(func, n=6).removeO()
evalfunc = lambdify(x, func, modules=['numpy'])
evaltaylor = lambdify(x, taylor, modules=['numpy'])
t = np.linspace(-7.5, 7.5 , 100)
plt.plot(t, evalfunc(t), 'b', label='sin(x)/x')
plt.plot(t, evaltaylor(t), 'r', label='Taylor')
plt.legend(loc='best')
plt.show()

Related

Create 3D graph from 2 variable function that uses linear algebra to solve system of equations

So, i'm doing this project for my electromagnetism class and I need to plot a 3D graph in python. I normally plot 3d graphs using meshgrids, but the function used to calculate the value uses linear algebra, and since meshgrids are matrices, it seems to be causing some problems. Does anyone know how to work around this problem?
This is the code I made:
#Vamos importar os módulos que precisamos
from math import *
from cmath import *
from numpy import linalg
import numpy as np
import matplotlib.pyplot as plt
import math
from pylab import meshgrid,cm,imshow,contour,clabel,colorbar,axis,title,show
from numpy import exp,arange
k=0.1
R1=0.4*3.5
R2=R1
L1=83e-6
L2=L1
C1=0.47e-6
C2=C1
Rc=10
M=k*sqrt(L1*L2)
V1=5
# the function that I'm going to plot
def CalcularTransformador(K,w):
Vp=2/pi*5
Rc=10
XL1=1j*w*L1
XL2=1j*w*L2
XC1=(-1j)/(w*C1)
XC2=(-1j)/(w*C2)
M=K*sqrt(L1*L2)
XM=1j*w*M
Z=np.array([[R1+XL1+XC1, -XM],[-XM, XL2+R2+(Rc*XC2)/(Rc+XC2)]])
V=np.array([Vp,0])
i=np.dot(linalg.inv(Z),V)
V2=i[1]*(XL2+R2+(Rc*XC2)/(Rc+XC2))
return i[0], i[1],V2
CalcularTransformador(0.1,150000)
w_angular=np.linspace(150000,260000,1000)
k=np.linspace(0,1,1000)
K,W = meshgrid(k, w_angular)
#print(K,W)
Valores = CalcularTransformador(K, W)
im = imshow(Valores,cmap=cm.RdBu)
show()

python: Plotting and optimizing the same function

Lets say I have the following function:
def f(x):
return log(3*exp(3*x) + 7*exp(7*x))
I want to do two things:
1) plot the function over a range of x-values
2) find the root of the function using the Newton method from scipy
My problem is that it seems that plotting is best done with a numpy array x=np.linspace(-2,2,1000), but then evaluating the function results in erros TypeError: only size-1 arrays can be converted to Python scalars. I can fix this by simply changing log and exp to np.log and np.exp, respectively.
But doing so then makes scipy.optimize.newton unhappy.
It seems like I need to define the function twice, once for use in plotting (with np. ...) and once for optimizing in the form given above.
I can't imagine that this is actually the case. Any hints would be greatly appreciated.
Seems legit, you just need to use numpy functions instead of base math functions:
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
%matplotlib inline
def f(x):
return np.log(3*np.exp(3*x) + 7*np.exp(7*x))
x = np.linspace(-2,2,1000)
y = f(x)
plt.scatter(x, y)
optimize.root(f, 1)

how to use solve_ivp solve Partial Differential Equations with spectral method?

I want to use the spectral method to solve partial differential equations. The equations like that, formula,the initial condition is u(t=0,x)=(a^2)*sech(x),u'_t (t=0)=0.
To solve it, I use the python with the spectral method. Following is the code,
import numpy as np
from scipy.integrate import solve_ivp
from scipy.fftpack import diff as psdiff
#RHS of equations
def f(t,u):
uxx= psdiff(u[N:],period=L,order=2)
du1dt=u[:N]
du2dt =a**2*uxx
dudt=np.append(du1dt,du2dt)
return dudt
a=1
amin=-40;bmax=40
L=bmax-amin;N=256
deltax=L/N
x=np.arange(amin,bmax,deltax)
u01 = 2*np.cosh(x)**(-1)
u02=np.zeros(N)
# y0
inital=np.append(u01,u02)
sola1 = solve_ivp(f, t_span=[0,40],y0=inital,args=(a,))
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(x,sola1.y[:N,5])
plt.show()
Following is my expected result,
expected result.
My python code can run,but I can't get the expected result,and can't find the problem.Following is the result from my python code,
my result
-----------------------------Update----------------------------------------------
I also try a new code,but still can't solve
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import odeint
from scipy.fftpack import diff as psdiff
from itertools import chain
def lambdifide_odes(y,t,a):
# uxx =- (1j)**2*k**2*u[:N]
u1=y[::2]
u2=y[1::2]
dudt=np.empty_like(y)
du1dt=dudt[::2]
du2dt=dudt[1::2]
du1dt=u2
uxx=psdiff(u1,order=2,period=L)
du2dt=a**2*uxx
return dudt
a=1
amin=-40;bmax=40
L=bmax-amin;N=256
deltax=L/N
x=np.arange(amin,bmax,deltax)
u01 = 2*np.cosh(x)**(-1)
u02=np.zeros(N)
initial=np.array(list(chain.from_iterable(zip(u01,u02))))
t0=np.linspace(0,40,100)
sola1 = odeint(lambdifide_odes,y0=initial,t=t0,args=(a,))
fig, ax = plt.subplots()
ax.plot(x,sola1[20,::2])
plt.show()
You have some slight problem with the design of your state vector and using this in the ODE function. The overall intent is that u[:N] is the wave function and u[N:] its time derivative. Now you want the second space derivative of the wave function, thus you need to use
uxx= psdiff(u[:N],period=L,order=2)
at the moment you use the time derivative, making this a mixed third derivative that does not occur in the equation.

How can I get the constant from an ODE in python?

My task is to calculate the constant from an ODE. So, I don't want to plot the function, I just want to get the result of the differential equation, and after that I need to calculate the c based on this assumption: v0=120 when t0=0.
I have started to implement with help of sympy module, and I get successfully the following result:[120.000000000000 -2.23606797749979/tanh(C1)]
But, after that I have no idea how I could get c1. Is it possible?
import inline as inline
import sympy as sp
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
from sympy import *
from sympy import lambdify
t=Symbol('t')
v = map(Function, 'v')
v=Function('v')
k=2
g=10
i=dsolve(Eq( Derivative(v(t), t)+k*v(t)**2, g), v(t))
j=i.subs(v(t),120).subs(t,0).evalf()
print(i)
print(j)
h=j.args
k=np.array(h)
If you want the value of C1 corresponding to the values of a given t and v(t) you could first solve for it and then substitute in the known values:
>>> C1 = [_ for _ in i.free_symbols if _.name == 'C1'][0]
>>> vals = solve(i, C1)
>>> [_.subs(v(t),120).subs(t,0).n(2) for _ in vals]
[-0.019 + 3.1*I, -0.019]

Runtime Return array size Error Python

I am trying to solve a simple differential equation using odeint function. It is giving an error with matching size of array. I think my initial_condi is not matching with the equation function. I can't figure it out where actually the error is. Blow is the error and code. Any help would be greatly appreciated.
RuntimeError: The size of the array returned by func (1) does not match the size of y0 (3)
from scipy import *
from scipy.integrate import odeint
from operator import itemgetter
import matplotlib as plt
from matplotlib.ticker import FormatStrFormatter
from pylab import *
from itertools import product
import itertools
from numpy import zeros_like
import operator
initial_condi = [1, 1, 1]
t_range = arange(0.0,60.0,1.0)
def equation(w, t):
T,I,V = w
dT= V*I*10.24-T*1.64
return dT
result_init = odeint(equation, initial_condi, t_range)
plt.plot(t, result_init[:, 0])
plt.show()
As your state vector has 3 components, the return value of the ODE function also needs to have 3 components, the derivatives of T,I,V. You only provided dT, but should return [dT, dI, dV ].

Categories

Resources