dsolve error: 'numpy.ndarray' object is not callable - python

import sympy as sp
sp.init_printing()
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display
Can somebody help me please?

The variable y is a numpy.ndarray, not a callable, which means it cannot be used like a function (or other callable) would: y(); only indexed, like y[]. You probably meant to write sp.Derivative(y[x],x).

I suspect that you want to solve a differential equation involving only scalar variables.
>>> import sympy as sp
>>> sp.var('x')
x
>>> f = sp.Function('f')
>>> sp.dsolve(sp.Derivative(f(x),x)-(1/(1+x**2)-2*f(x)**2))
Eq(f(x), x**3*(2*C1*(C1 - 1) - 1)/3 + x**5*(C1*(16*C1*(-9*C1 + 1) - 13*C1 + 2) - 20*C1 + 12)/30 + C1 + C1*x + C1*x**4*(13*C1 + 2)/6 - C1**2*x**2 + O(x**6))
If you have an initial condition and need to solve for the arbitary constant then Represent a first order differential equation in numpy might help. (I don't know for sure.)

Related

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 ].

Solving Equation for a variable in Python

I am trying to solve an equation for an unknown variable(y), I am using the below. However it is taking lot of time, I have read some article about using scipy.optimize to speed it, but not sure how to. Any help will be appreciated:
from sympy import Eq, var, solve
var('y')
eq = Eq(((5/(1+((.0025+y)/2)))**2) + ((5/(1+((.0027+y)/2)))**4) + ((105/(1+((.003+y)/2)))**6),104.90)
solve(eq)
If you are looking for a numeric solution, you can use brentq
from scipy.optimize import brentq
f = lambda y: ((5/(1+((.0025+y)/2)))**2) + ((5/(1+((.0027+y)/2)))**4) + ((105/(1+((.003+y)/2)))**6)-104.90
res = brentq(f, 0, 1E8)

Plotting the output of a function gives this error-TypeError: unhashable type: 'numpy.ndarray'

I tried to plot the output of the defined function with respect to z. However the error TypeError: unhashable type: 'numpy.ndarray' is shown. Please help.
import numpy as np
import matplotlib.pyplot as plt
import sympy as sp
a=1.48185562
b=0.57081914
c=-0.25098188
H0=70.32724312
z=np.linspace(0.0,1.5,100)
omega_m0=0.3
dlabel= 'w(z) vz z'
def func(z):
sp.var('z+1')
H=((2/H0)*((b*(z+1)+c*(z+1)**0.5+2.0-a-b-c)*(1-0.5*a*(z+1)**(-0.5)) - ((z+1)-a*(z+1)**0.5-1.0+a)*(b+c*0.5*(z+1)**(-0.5)))/(b*(z+1)+c*(z+1)**0.5+2.0-a-b-c)**2)**(-1)
return ((2*(z+1)/3)*(sp.diff(sp.log(H)))-1)/(1-(H/H0)**2*omega_m0*(z+1)**3)
wz=func(z)
plt.plot(z,wz)
plt.xlabel('z')
plt.ylabel('w(z)')
plt.show()
I'm not sure what you want to do with sp.var('z+1')... at least I hope you were not trying to create a variable named z+1. I got the code to run but I let you make sure it does what you want and complain if not :)
import numpy as np
import matplotlib.pyplot as plt
import sympy as sp
a=1.48185562
b=0.57081914
c=-0.25098188
H0=70.32724312
x=np.linspace(0.0,1.5,100)
omega_m0=0.3
dlabel= 'w(z) vz z'
sp.var('z')
def func(z):
H=((2/H0)*((b*(z+1)+c*(z+1)**0.5+2.0-a-b-c)*(1-0.5*a*(z+1)**(-0.5)) - ((z+1)-a*(z+1)**0.5-1.0+a)*(b+c*0.5*(z+1)**(-0.5)))/(b*(z+1)+c*(z+1)**0.5+2.0-a-b-c)**2)**(-1)
return ((2*(z+1)/3)*(sp.diff(sp.log(H)))-1)/(1-(H/H0)**2*omega_m0*(z+1)**3)
wz = [func(z).evalf(subs = {z : y}) for y in x]
plt.plot(x,wz)
plt.xlabel('z')
plt.ylabel('w(z)')
plt.show()
EDIT: in order to get wz, the following piece is much faster ( cf Evaluate sympy expression from an array of values ):
from sympy.utilities.lambdify import lambdify
func_np_ready = lambdify(z, func(z),'numpy') # returns a numpy-ready function
wz = func_np_ready(x)
You may be better off flagging your question with sympy - it's probably the behaviour of one of those functions that's causing the issue, and someone else might know all about it.
It's probably a good idea to split those really long formulas up into multi lines (at least while debugging) to help you track down the error. Also put in some prints etc.
I know it's not what you want to achieve but if I cut out the sympy (I don't have it installed!) and adjust the array lengths it plots without error:
...
H=((2/H0)*((b*(z+1)+c*(z+1)**0.5+2.0-a-b-c)*(1-0.5*a*(z+1)**(-0.5)) - ((z+1)-a*(z+1)**0.5-1.0+a)*(b+c*0.5*(z+1)**(-0.5)))/(b*(z+1)+c*(z+1)**0.5+2.0-a-b-c)**2)**(-1)
return ((2*(z[:-1]+1)/3)*(np.diff(np.log(H)))-1)/(1-(H[:-1]/H0)**2*omega_m0*(z[:-1]+1)**3)
wz=func(z)
plt.plot(z[:-1],wz)

Definite integral over one variable in a function with two variables in Scipy

I am trying to calculate the definite integral of a function with multiple variables over just one variable in scipy.
This is kind of like what my code looks like-
from scipy.integrate import quad
import numpy as np
def integrand(x,y):
return x*np.exp(x/y)
quad(integrand, 1,2, args=())
And it returns this type error:
TypeError: integrand() takes exactly 2 arguments (1 given)
However, it works if I put a number into args. But I don't want to, because I want y to remain as y and not a number. Does anyone know how this can be done?
EDIT: Sorry, don't think I was clear. I want the end result to be a function of y, with y still being a symbol.
Thanks to mdurant, here's what works:
from sympy import integrate, Symbol, exp
from sympy.abc import x
y=Symbol('y')
f=x*exp(x/y)
integrate(f, (x, 1, 2))
Answer:
-(-y**2 + y)*exp(1/y) + (-y**2 + 2*y)*exp(2/y)
You probably just want the result to be a function of y right?:
from scipy.integrate import quad
import numpy as np
def integrand(x,y):
return x*np.exp(x/y)
partial_int = lambda y: quad(integrand, 1,2, args=(y,))
print partial_int(5)
#(2.050684698584342, 2.2767173686148355e-14)
The best you can do is use functools.partial, to bind what arguments you have for the moment. But one fundamentally cannot numerically integrate a definite integral if you havnt got the entire domain specified yet; in that case the resulting expression will necessarily still contain symbolic parts, so the intermediate result isn't numerical.
(Assuming that you are talking about computing the definite integral over x given a specific, fixed value of y.)
You could use a lambda:
quad(lambda x:integrand(x, 10), 1, 2, args=())
or functools.partial():
quad(functools.partial(integrand, y=10), 1, 2, args=())
from scipy.integrate import quad
import numpy as np
def integrand(x,y):
return x*np.exp(x/y)
vec_int = np.vectorize(integrand)
y = np.linspace(0, 10, 100)
vec_int(y)

Categories

Resources