I need to solve a 2nd order ODE which I have decoupled into two first order ODEs. I've tried solving it using solve_ivp, but it doesn't seem to provide the solution I expect. I have provided the code below.
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import derivative
from scipy.integrate import solve_ivp
from matplotlib import rc
rc('text', usetex = True)
V0 = 2*10**-10
A = 0.130383
f = 0.129576
phi_i_USR2 = 6.1
phi_Ni_USR2 = 1.2
def V_USR2(phi):
return V0*(np.tanh(phi/np.sqrt(6)) + A*np.sin(1/f*np.tanh(phi/np.sqrt(6))))**2
def V_phi_USR2(phi):
return derivative(V_USR2, phi)
N = np.linspace(0,66,1000)
def USR2(N, X):
phi, g = X
return [g, (g**2/2 - 3)*(V_phi_USR2(phi)/V_USR2(phi) + g)]
X0 = [phi_i_USR2, phi_Ni_USR2]
sol = solve_ivp(USR2, (0,66), X0, method = 'LSODA', t_eval = N)
phi_USR2 = sol.y[0]
phi_N_USR2 = sol.y[1]
N_USR2 = sol.t
plt.plot(phi_USR2, phi_N_USR2)
plt.xlabel("$\phi$")
plt.ylabel("$\phi'$")
plt.title("Phase plot for USR2")
plt.show()
solve_ivp gives me the following plot:
The problem is that there is supposed to be an oscillation near the origin, which is not well captured by solve_ivp. However, for the same equation and initial conditions, Mathematica gives me exactly what I want:
I want the same plot in Python as well. I tried various methods in solve_ivp such as RK45, LSODA, Radau and BDF, but all of them show the same problem (LSODA tries to depict an oscillation but fails, but the other methods don't even move past the point where the oscillation starts). It would be great if someone can shed light on the problem. Thanks in advance.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am trying to find a solution to a problem, I have searched and the closest I can find is a post on interpolation from these forums which I have been able to achieve limited success.
I have multiple polygon's defined as separate scatter plots given by a number of x-y points. What I am attempting to do is draw a horizontal line on the y-axis and find x-min and x-max values at which the horizontal line intersects the polygon. I would like to do this for the full range of y-values. So in theory I could step through a loop and record the values at y=1, y=2 etc. An engineering software I am using requires input parameters in this format hence my attempt to find a solution.
Any advise or pointers on the best approach to this problem would be much appreciated and I will give it a go.
import matplotlib.pyplot as plt
import numpy as np
x =[1,2.6,2.56,2.57,10,11.66,13.07,11.78,11.27,6.49,5.98,5.76,3.02,1.87,1]
y =[15.59,15.09,15.14,15.15,16,17,25.47,26,27,27,28,28,26.67,16.37,15.59]
plt.plot(x,y)
plt.grid()
plt.show()
You can linearly interpolate between those two points, where the polygon crosses the line defined by ys==?. To find those points, you may substract the ys value from the y values of the polygon, find those points between which the sign changes and get the minimum and maximum of those points.
import numpy as np
import matplotlib.pyplot as plt
x =[1,2.6,2.56,2.57,10,11.66,13.07,11.78,11.27,6.49,5.98,5.76,3.02,1.87,1]
y =[15.59,15.09,15.14,15.15,16,17,25.47,26,27,27,28,28,26.67,16.37,15.59]
def findminmax(t, x, zero=0):
t = np.array(t); x = np.array(x)
ta = []
p = (x-zero) > 0
ti = np.where(np.bitwise_xor(p[1:], p[:-1]))[0]
for i in ti:
y_ = np.sort(x[i:i+2])
z_ = t[i:i+2][np.argsort(x[i:i+2])]
t_ = np.interp(zero, y_, z_)
ta.append( t_ )
if ta:
return min(ta), max(ta)
else:
return None, None
plt.plot(x,y)
ys = np.arange(13, 29, 0.2)
result = []
for s in ys:
mi, ma = findminmax(x,y,zero=s)
if mi and ma:
result.append([mi,ma,s])
print("y = {}, minimum {}, maximum {}".format(s,mi,ma))
result=np.array(result)
plt.scatter(result[:,0],result[:,2], label="min", color="limegreen")
plt.scatter(result[:,1],result[:,2], label="max", color="crimson")
plt.legend()
plt.grid()
plt.show()
I wrote a code to solve a differential problem (here I used a euler method just to check if it works, later I will use RK4 method). But I would like to turn it into a programm where the user input the function fun (defined as dx/dt=fun). Here my code :
from math import*
from pylab import*
import numpy as np
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
t0=0.0;
x0=1.0; #conditions initiales
tmax=1.0; #temps max
h=0.01; #pas d'integration
N=int(abs(tmax-t0)/h)+1; #+1 pour arriver a T[N]=Tmax
X=np.zeros(N) #indice de n=0 -> N-1 (il y en a N)
T=np.zeros(N)
fun="-6.0*x";
def F(x1,t1):
x=x1;
t=t1;
F=eval(fun);
return F;
T[0]=t0;
X[0]=x0;
for i in range(1,N):
T[i]=T[i-1]+h;
X[i]=X[i-1]+F(X[i],T[i])*h;
plt.plot(T,X,label="Solution");
plt.title('RĂ©solution EDO ordre 1');
plt.xlabel('t');
plt.ylabel('x(t)');
plt.show();
legend()
My question is : the function F is defined with a eval function, and I read it is bad to use that. Have you other propositions ? Thanks !
Here is my first steps within the NumPy world.
As a matter of fact the target is plotting below 2-D function as a 3-D mesh:
N = \frac{n}{2\sigma\sqrt{\pi}}\exp^{-\frac{n^{2}x^{2}}{4\sigma^{2}}}
That could been done as a piece a cake in Matlab with below snippet:
[x,n] = meshgrid(0:0.1:20, 1:1:100);
mu = 0;
sigma = sqrt(2)./n;
f = normcdf(x,mu,sigma);
mesh(x,n,f);
But the bloody result is ugly enough to drive me trying Python capabilities to generate scientific plots.
I searched something and found that the primary steps to hit above mark in Pyhton might be acquired by below snippet:
from matplotlib.patches import Polygon
import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
sigma = 1
def integrand(x,n):
return (n/(2*sigma*np.sqrt(np.pi)))*np.exp(-(n**2*x**2)/(4*sigma**2))
t = np.linespace(0, 20, 0.01)
n = np.linespace(1, 100, 1)
lower_bound = -100000000000000000000 #-inf
upper_bound = t
tt, nn = np.meshgrid(t,n)
real_integral = quad(integrand(tt,nn), lower_bound, upper_bound)
Axes3D.plot_trisurf(real_integral, tt,nn)
Edit: With due attention to more investigations on Greg's advices, above code is the most updated snippet.
Here is the generated exception:
RuntimeError: infinity comparisons don't work for you
It is seemingly referring to the quad call...
Would you please helping me to handle this integrating-plotting problem?!...
Best
Just a few hints to get you in the right direction.
numpy.meshgrid can do the same as MatLABs function:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html
When you have x and n you can do math just like in matlab:
sigma = numpy.sqrt(2)/n
(in python multiplication/division is default index by index - no dot needed)
scipy has a lot more advanced functions, see for example How to calculate cumulative normal distribution in Python for a 1D case.
For plotting you can use matplotlibs pcolormesh:
import matplotlib.pyplot as plt
plt.pcolormesh(x,n,real_integral)
Hope this helps until someone can give you a more detailed answer.
I am using python's fsolve to find roots of a set of equations using the script below:
from scipy.optimize import fsolve
from scipy.interpolate import spline
import math
import numpy as np
#from mpldatacursor import datacursor
%pylab
from matplotlib import pyplot as plt
import matplotlib.dates as mdates
%matplotlib inline
def equations(p):
x,y,z = p
f1 = (1 - 2*math.cos(math.radians(x)) + 2*math.cos(math.radians(y)) - 2*math.cos(math.radians(z)) + 0.8)
f2 = (1 - 2*math.cos(math.radians(5*x)) + 2*math.cos(math.radians(5*y)) - 2*math.cos(math.radians(5*z)))
f3 = (1 - 2*math.cos(math.radians(7*x)) + 2*math.cos(math.radians(7*y)) - 2*math.cos(math.radians(7*z)))
return (f1,f2,f3)
x,y,z = fsolve(equations,(0,0,0))
#print equations((x,y,z))
This works perfect with one small issue. This generates only one set of solution i.e., one value for each x, y, z to satisfy those equations, but since these are trigonometric there should be atleast 2 solutions. How can I use fsolve (or anything else) to find two solutions for x, y, z for a given starting point.
Example: for x,y,z = fsolve(equations,(0,0,0)), is it possible to generate two values for x,y,z instead of one solution?
Thanks for the help.