Search code examples
pythonmatplotlibplotwolfram-mathematicapolar-coordinates

Plotting phase portraits in Python using polar coordinates


I need a phase portrait of the following nonlinear system given in polar form...

\dot{r} = 0.5*(r - r^3)
\dot{\theta} = 1

I know how to do it in Mathematica...

field1 = {0.5*(r - r^3), 1};
p1 = StreamPlot[Evaluate@TransformedField["Polar" -> "Cartesian", field1, {r, \[Theta]} -> {x, y}], {x, -3, 3}, {y, -3, 3}, Axes -> True, StreamStyle -> Gray, ImageSize -> Large];
Show[p1, AxesLabel->{x,y}, ImageSize -> Large]

enter image description here

How can I do the same using pyplot.quiver in Python?


Solution

  • Correction of the previous answer:

    • From x=r*cos(theta) one gets dx = dr*cos(theta)-r*sin(theta)*dtheta = x*dr/r-y*dtheta,
    • From y=r*sin(theta) one gets dy = dr*sin(theta)+r*cos(theta)*dtheta = y*dr/r+x*dtheta,
    • one can use the vectorized operations of numpy to avoid all loops
    def dF(r, theta):
        return 0.5*r*(1 - r*r), 1+0*theta
    
    X, Y = np.meshgrid(np.linspace(-3.0, 3.0, 30), np.linspace(-3.0, 3.0, 30))
    R, Theta = (X**2 + Y**2)**0.5, np.arctan2(Y, X)
    dR, dTheta = dF(R, Theta)
    C, S = np.cos(Theta), np.sin(Theta)
    U, V = dR*C - R*S*dTheta, dR*S+R*C*dTheta
    
    plt.streamplot(X, Y, U, V, color='r', linewidth=0.5, density=1.6)
    plt.axis('square')
    plt.axis([-3, 3, -3, 3])
    plt.show()
    

    This gives the plot below. Use the density option of streamplot to increase the density of plot lines.

    enter image description here