如何绘制庞加莱部分? (Duffing Oscillator)

时间:2017-11-27 22:34:45

标签: fortran numerical-methods differential-equations

我编写了一个程序,成功显示了Duffing方程的简单极限环。但是,我现在需要为此案例绘制庞加莱部分。

我需要通过以固定的时间间隔拍摄相空间图的快照来实现这一点,例如t*omega = 2*pi*n。正如我在这种情况下将omega设置为1,这就是t = 2*pi*n时的情况。我试过这个,但是没有得到我期望的庞加莱部分。

这是我的代码:

program rungekutta
implicit none
integer, parameter :: dp = selected_real_kind(15,300)
integer :: i, n
real(kind=dp) z, y, t, A, C, D, B, omega, h
open(unit=100, file="rungekutta.dat",status='replace')
n = 0
!constants
omega = 1.0_dp
A = 0.25_dp
B = 1.0_dp
C = 0.1_dp
D = 1.0_dp
y = 0.0_dp
z = 0.0_dp
t = 0.0_dp
do i=1,1000
call rk2(z, y, t, n)
n = n + 1.0_dp
write(100,*) y, z
end do

contains
subroutine rk2(z, y, t, n) !subroutine to implement runge-kutta algorithm
implicit none
integer, parameter :: dp = selected_real_kind(15,300)
integer, intent(inout) :: n
real(kind=dp) :: k1y, k1z, k2y, k2z, y, z, t, pi
pi = 4.0*ATAN(1.0)
h = 0.1_dp
t = n*2*pi
k1y = dydt(y,z,t)*h
k1z = dzdt(y,z,t)*h
k2z = dzdt(y + (0.5_dp*k1y), z + (0.5_dp*k1z), t + (0.5_dp*h))*h
k2y = dydt(y, z +(0.5_dp*k1z), t)*h
y = y + k2y
z = z + k2z
end subroutine

!2nd order ODE split into 2 for coupled Runge-Kutta, useful to define 2 
functions
function dzdt(y,z,t)
real(kind=dp) :: y, z, t, dzdt
dzdt = -A*y**3.0_dp + B*y - C*z + D*sin(omega*t)
end function

function dydt(y,z,t)
real(kind=dp) ::  z, dydt, y, t
dydt = z
end function
end program

我还附上了我的庞加莱部分的图像:

Poincaré section

这是x轴与dydt的y。

我想要的图像:enter image description here

1 个答案:

答案 0 :(得分:1)

rk2例程中,您执行步长0.1一个步骤。因此,该图是该分辨率下解的完整轨迹。然而,打算似乎要整合一整段时间。这需要在该例程中循环。

换句话说,根据您的代码(y(n*T), z(n*T)),您想要的是T其中T=2*p是系统期间之一的情节。您实际计算的是(y(n*h), z(n*h)),其中h=0.1是RK2单步的步长。

k2y的论据也需要根据user5713492的评论予以纠正

使用经过校正的积分器,您应该得到如下图所示的内容:

phase portrait with Poincaré section

其中红色方块是t=n*2*pi处的点。溶液曲线上的点所指示的步长与h=0.1相同,积分超过t=0..300

def RK2(f,u,times,subdiv = 1):
     uout = np.zeros((len(times),)+u.shape)
     uout[0] = u;
     for k in range(len(times)-1):
         t = times[k]
         h = (times[k+1]-times[k])/subdiv
         for j in range(subdiv):
            k1 = f(u,t)*h
            k2 = f(u+0.5*k1, t+0.5*h)*h
            u, t = u+k2, t+h
         uout[k+1]=u
     return uout

def plotphase(A,B,C,D):
     def derivs(u,t): y,z = u; return np.array([ z, -A*y**3 + B*y - C*z + D*np.sin(t) ])
     N=60
     u0 = np.array([0.0, 0.0])
     t  = np.arange(0,300,2*np.pi/N); 
     u  = RK2(derivs, u0, t, subdiv = 10)
     plt.plot(u[:-2*N,0],u[:-2*N,1],'.--y', u[-2*N:,0],u[-2*N:,1], '.-b', lw=0.5, ms=2);
     plt.plot(u[::N,0],u[::N,1],'rs', ms=4); plt.grid(); plt.show()

plotphase(0.25, 1.0, 0.1, 1.0)