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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何绘制庞加莱部分? (Duffing Oscillator)相关的知识,希望对你有一定的参考价值。

我写了一个程序,成功地显示了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

答案

在你的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)

以上是关于如何绘制庞加莱部分? (Duffing Oscillator)的主要内容,如果未能解决你的问题,请参考以下文章

找回纯洁的内心

找回纯洁的内心

如何在 Csound 中的乐器定义中包含持续时间

贝加莱PLC。写入后计算新偏移量或如何将数据写入新行

《天天数学》连载63:三月三日

《天天数学》连载63:三月三日