Noted that in one of the integrals that I put into sympy the tool stopped.
integrate((sinhx)/(exp(5*x)-1),x)
I tried to rewrite the sinh-function and I put exp(x) = y.
Well, I obtained a product of polinomial function. On the denominator, one factor was:
y^4+y^3+y^2+y+1
The tool found the roots(4) but the previous poly can write on this way:
(y^2+ay+b)(y^2+cy+d)
The solution of the integral go for this step (factorize the polinomial on the way above) and sympy stopped here.
On various sites I see the final symbolic solution.
Is there a method on sympy to solve this kind of integrals?Thanks.A.
Related
So, I have to solve numerically the following ODE y''+f(y)*(y')^2 = 0: ODE
originally between [y_i,y_f] where y = y(t) and y(0) = y_i. The main problem is that the function f(y) has a (regular) singular point (couldn't post the image).
Also, f(y) is obtained from long numerical calculations, so I have no analytical expression for it. The issue is that the singular point lies between y_i and y_f. So far, I could not find any method which helps me to solve this kind of problem. It doesn't matter if it can be solved as a BVP o IVP, but I need to cross the singularity.
What I have tried:
I approximated f(y) as -2/(y-y*), where y* is the singularity, and tried to solved the problem as a IVP using Runge-kutta, odeint and Runge-Kutta-Fehlberg method. But I cannot cross it.
I tried to cheat using RKF, as y tends to be constant I manually increased it, forcing it to cross the singular point, but then the solution increase to infinity, so not a valid solution.
Same as before, but using the numerically defined function f(y), not its approx.
The same but as BVP using the shooting method and solve_bvp from Python.
You can immediately integrate after dividing by y' to get ln(y')+F(y)=c or y'*exp(F(y))=C, F'=f, so that in principle you could compute t(y) via simple quadrature, and then get the solution y(t) via inversion of the function value table.
Your example integrates to y'=C*(y-y*)^2, y(t)=y(0)/(1-C*y(0)*t), which could also lead to a singularity in the solution formula due to the denominator. This means that even if a solution exists, you will have to start quite close to it, else the solution process might have to cross a surface of singular Jacobians or other impossibilities, and will fail to continue at this point.
Consider for the sake of simplicity the following equation (Burgers equation):
Let's solve it using scipy (in my case scipy.integrate.ode.set_integrator("zvode", ..).integrate(T)) with a variable time-step solver.
The issue is the following: if we use the naïve implementation in Fourier space
then the viscosity term nu * d2x(u[t]) can cause an overshoot if the time step is too big. This can lead to a fair amount of noise in the solutions, or even to (fake) diverging solutions (even with stiff solvers, on slightly more complex version of this equation).
One way to regularize this is to evaluate the viscosity term at step t+dt, and the update step becomes
This solution works well when programmed explicitly. How can I use scipy's variable-step ode solver to implement it ? To my surprise I haven't found any documentation on this fairly elementary thorny issue...
You actually can't, or on the other extreme, odeint or ode->zvode already does that to any given problem.
To the first, you would need to give the two parts of the equation separately. Obviously, that is not part of the solver interface. Look at DDE and SDE solvers where such a partition of the equation is actually required.
To the second, odeint and ode->zvode use implicit multi-step methods, which means that the values of u(t+dt) and the right side there enter the computation and the underlying local approximation.
You could still try to hack your original approach into the solver by providing a Jacobian function that only contains the second derivative term, but quite probably you will not achieve an improvement.
You could operator-partition the ODE and solve the linear part separately introducing
vhat(k,t) = exp(nu*k^2*t)*uhat(k,t)
so that
d/dt vhat(k,t) = -i*k*exp(nu*k^2*t)*conv(uhat(.,t),uhat(.,t))(k)
I'm trying to solve a first-order ODE in Python:
where Gamma and u are square matrices.
I don't explicitly know u(t) at all times, but I do know it at discrete timesteps from doing an earlier calculation.
Every example I found of Python's solvers online (e.g. this one for scipy.integrate.odeint and scipy.integrate.ode) know the expression for the derivative analytically as a function of time.
Is there a way to call these (or other differential equation solvers) without knowing an analytic expression for the derivative?
For now, I've written my own Runge-Kutta solver and jitted it with numba.
You can use any of the SciPy interpolation methods, such as interp1d, to create a callable function based on your discrete data, and pass it to odeint. Cubic spline interpolation,
f = interp1d(x, y, kind='cubic')
should be good enough.
Is there a way to call these (or other differential equation solvers) without knowing an analytic expression for the derivative?
Yes, none of the solvers you mentioned (nor most other solvers) require an analytic expression for the derivative. Instead they call a function you supply that has to evaluate the derivative for a given time and state. So, your code would roughly look something like:
def my_derivative(time,flat_Gamma):
Gamma = flat_Gamma.reshape(dim_1,dim_2)
u = get_u_from_time(time)
dGamma_dt = u.dot(Gamma)
return dGamma_dt.flatten()
from scipy.integrate import ode
my_integrator = ode(my_derivative)
…
The difficulty in your situation is rather that you have to ensure that get_u_from_time provides an appropriate result for every time with which it is called. Probably the most robust and easy solution is to use interpolation (see the other answer).
You can also try to match your integration steps to the data you have, but at least for scipy.integrate.odeint and scipy.integrate.ode this will be very tedious as all the integrators use internal steps that are inconvenient for this purpose. For example, the fifth-order Dormand–Prince method (DoPri5) uses internal steps of 1/5, 3/10, 4/5, 8/9, and 1. This means that if you have temporally equidistant data for u, you would need 90 data points for each integration step (as 1/90 is the greatest common divisor of the internal steps). The only integrator that could make this remotely feasible is the Bogacki–Shampine integrator (RK23) from cipy.integrate.solve_ivp with internal steps of 1/2, 3/4, and 1.
I would like to use sympy to solve a definite integral that I know that Mathematica can solve. In Mathematica the following line
Integrate[z^2 (BesselI[0, z^2] - BesselI[1, z^2]) Exp[-z^2], {z, 0, x}]
yields
1/3 x^3 HypergeometricPFQ[{1/2,3/2},{1,5/2},-2 x^2]-1/10 x^5 HypergeometricPFQ[{3/2,5/2},{3,7/2},-2 x^2]
It would prefer to use python with sympy for this and I try to with the following code
import sympy;
x, z = sympy.var('x z');
sympy.integrate( z**2*(sympy.besseli(0,z**2)-sympy.besseli(1,z**2))*sympy.exp(-z**2) ,(z,0,x));
Unfortunately, the computation just hangs. I give up after about 30-40 minutes of waiting. In Mathematica, it takes less than a second. If I change the integrand, then I can get sympy to solve it. Such as
sympy.integrate( z**2*sympy.besseli(0,z**2) ,(z,0,x));
yields
x**3*gamma(3/4)*hyper((3/4,), (1, 7/4), -x**4/4)/(4*gamma(7/4))
I am a long time Mathematica user and have a pretty good sense of how to get it to solve tricky integrals. As a new sympy users I lack that experience.
Are there any flags I could add?
Are there other ways to solve this problem in sympy?
If this integral is not possible with sympy, is there a way to understand sympy's limitations? Such as how sympy does integration versus Mathematica.
I tried the following integral in SymPy 0.7.3:
import sympy
from sympy import cos, sin, pi
sympy.var('x, L')
sympy.var('i, k', integer=True)
integrand = cos(pi*i*x/L)**2*cos(pi*k*x/L)**2*sin(pi*i*x/L)*sin(pi*k*x/L)
print(sympy.integrate(integrand, (x, 0, L), conds='none'))
I already tried not using the conds argument and not using integer=True when declaring i, k without success.
Is there any other workaround to solve this integral?
The solution for this integral is 0.
NOTE:
There are other similar integrands for which SymPy hangs if someone is interested.
I've noticed a trend of SymPy to hang when the simplifications along the integrations lead to 0 terms, so maybe the problem is in a simplification algorithms applied along the integration.
Unfortunately, currently SymPy's ability to deal with trigonometric integrals is not that great. There are maybe some forms that it will deal with better than others (you can play with trigsimp'ing the input to see if it helps).
If you don't mind dealing with the output, you can rewrite the integrand in terms of complex exponentials. SymPy is much better at integrating those. Use .rewrite(exp). You'll have to use .rewrite(sin) and simplify at the end to get it back in terms of trig functions, though. Unfortunately, it doesn't really help for this particular integral :(
Better trigonometric integration is coming. The work from https://github.com/sympy/sympy/pull/2380 needs to be finished, and one more algorithm implemented.