我编写了一个程序,成功显示了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
我还附上了我的庞加莱部分的图像:
这是x轴与dydt的y。
答案 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的评论予以纠正
使用经过校正的积分器,您应该得到如下图所示的内容:
其中红色方块是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)