* PROGRAM poincare * plot phase diagram and Poincare map for damped, driven pendulum IMPLICIT NONE REAL*8 A, ang_vel, dA, dt, gamma, t, theta INTEGER IC1_, IC2_, IR_, istep, nstep CHARACTER*80 flag LOGICAL Ltmp1_, TBkeyinput DATA IC1_/1/ DATA IC2_/2/ CALL GWopen(IR_, 0) CALL initial(theta,ang_vel,gamma,A,t,dt,nstep,dA,IC1_,IC2_,flag) CALL set_up_windows(A,IC1_,IC2_) CALL draw_axes(A,IC1_,IC2_) Ltmp1_ = .TRUE. DO WHILE(Ltmp1_) DO istep = 1, nstep CALL RK4(theta,ang_vel,gamma,A,t,dt) CALL phase_space(theta,ang_vel,IC1_) END DO CALL Poincare(theta,ang_vel,IC2_) IF(TBkeyinput()) CALL change_amplitude(A,dA,IC1_,IC2_,flag) Ltmp1_ = flag .NE. 'stop' END DO CALL GWquit(IR_) END C SUBROUTINE initial(theta0,ang_vel0,gamma,A,t0,dt,nstep,dA,IC1_ +,IC2_,flag) IMPLICIT NONE REAL*8 T, pi, theta0, ang_vel0, gamma, A, t0, dt, dA REAL GWaspect PARAMETER(pi = 3.141592653589793D0) INTEGER IR_, nstep, IC1_, IC2_ CHARACTER*80 flag WRITE(*,'(A,$)') 'initial angle = ' READ(*,*) theta0 WRITE(*,'(A,$)') 'initial angular velocity = ' READ(*,*) ang_vel0 t0 = 0 ! initial time WRITE(*,'(A,$)') 'damping constant = ' READ(*,*) gamma WRITE(*,'(A,$)') 'amplitude of external force = ' READ(*,*) A * angular frequency of external force equals two and * hence period of external force equals pi nstep = 100 ! # iterations between Poincare plot T = pi ! period of external force dt = T/nstep ! time step dA = 0.01D0 ! increase in amplitude of external force * left-side of screen for phase space plot CALL GWvport(IR_, 0.0, 0.0, 0.49*GWaspect(1), 1.0) * open second window for Poincare map CALL GWsavevp(IR_, IC1_) CALL GWsetogn(IR_, 0, IC1_) CALL GWvport(IR_, 0.51*GWaspect(1), 0.0, GWaspect(1), 1.0) flag = '' CALL GWsavevp(IR_, IC2_) CALL GWsetogn(IR_, 0, IC2_) END C SUBROUTINE set_up_windows(A,IC1_,IC2_) IMPLICIT NONE REAL*8 A REAL vmax, pi PARAMETER(pi = 3.141592) INTEGER IR_, IC1_, IC2_ vmax = REAL(4*A) CALL GWselvp(IR_, IC1_) CALL GWsetogn(IR_, 0, IC1_) CALL GWindow(IR_, -pi, -vmax, pi, vmax) CALL GWselvp(IR_, IC2_) CALL GWsetogn(IR_, 0, IC2_) CALL GWindow(IR_, -pi, -vmax, pi, vmax) END C SUBROUTINE draw_axes(A,IC1_,IC2_) IMPLICIT NONE CHARACTER*80 Stmp1_ REAL*8 A REAL vmax, pi PARAMETER(pi = 3.141592) INTEGER IR_, IC1_, IC2_ CALL GWclear(IR_, -1) CALL GWselvp(IR_, IC1_) CALL GWsetogn(IR_, 0, IC1_) CALL GWerase(IR_, IC1_, -1) CALL GWsetpen(IR_, 0, -1, -1, -1) vmax = 4*A CALL GWline(IR_, 0.0, -vmax, 0.0, vmax) CALL GWline(IR_, -pi, 0.0, pi, 0.0) WRITE(Stmp1_, '(A,F7.5)') 'A = ',A CALL GWputtxt(IR_, -3.0, vmax*22.5/24, Stmp1_) CALL GWselvp(IR_, IC2_) CALL GWsetogn(IR_, 0, IC2_) CALL GWerase(IR_, IC2_, -1) CALL GWsetpen(IR_, 0, -1, -1, -1) CALL GWline(IR_, -pi, 0.0, pi, 0.0) CALL GWline(IR_, 0.0, -vmax, 0.0, vmax) END C SUBROUTINE RK4(theta,ang_vel,gamma,A,t,dt) * fourth-order Runge Kutta algorithm IMPLICIT NONE REAL*8 k1v, k1x, k2v, k2x, k3v, k3x, k4v, k4x, pi, theta, + ang_vel, gamma, A, t, dt, force PARAMETER(pi = 3.141592653589793D0) k1v = force(theta,ang_vel,gamma,A,t)*dt k1x = ang_vel*dt t = t + 0.5D0*dt k2v = force(theta+0.5D0*k1x,ang_vel+0.5D0*k1v,gamma,A,t)*dt k2x = (ang_vel + 0.5D0*k1v)*dt k3v = force(theta+0.5D0*k2x,ang_vel+0.5D0*k2v,gamma,A,t)*dt k3x = (ang_vel + 0.5D0*k2v)*dt t = t + 0.5D0*dt k4v = force(theta+k3x,ang_vel+k3v,gamma,A,t)*dt k4x = (ang_vel + k3v)*dt ang_vel = ang_vel + (k1v + 2*k2v + 2*k3v + k4v)/6 theta = theta + (k1x + 2*k2x + 2*k3x + k4x)/6 IF(theta .GT. pi) theta = theta - 2*pi IF(theta .LT. -pi) theta = theta + 2*pi END C FUNCTION force(theta,ang_vel,gamma,A,t) * A is amplitude of driving force IMPLICIT NONE REAL*8 force, theta, ang_vel, gamma, A, t force = -gamma*ang_vel - (1 +2*A*cos(2*t))*sin(theta) END C SUBROUTINE phase_space(theta,ang_vel,IC9_) IMPLICIT NONE REAL*8 theta, ang_vel INTEGER IR_, IC9_ CALL GWselvp(IR_, IC9_) CALL GWsetogn(IR_, 0, IC9_) CALL GWsetpxl(IR_, REAL(theta), REAL(ang_vel), 13) END C SUBROUTINE change_amplitude(A,dA,IC1_,IC2_,flag) IMPLICIT NONE REAL*8 A, dA INTEGER k, IC1_, IC2_ CHARACTER*80 flag CALL TBgetkey(k) IF(k .EQ. ICHAR('s')) flag = 'stop' IF(k .EQ. ICHAR('i')) A = A + dA IF(k .EQ. ICHAR('d')) A = A - dA IF(k .EQ. ICHAR('i') .OR. k .EQ. ICHAR('d')) THEN CALL set_up_windows(A,IC1_,IC2_) END IF IF(flag .EQ. '') CALL draw_axes(A,IC1_,IC2_) END C SUBROUTINE Poincare(theta,ang_vel,IC9_) * plot points and allow for change in amplitude of external force IMPLICIT NONE REAL*8 theta, ang_vel INTEGER IR_, IC9_ CALL GWselvp(IR_, IC9_) CALL GWsetogn(IR_, 0, IC9_) CALL GWsetpxl(IR_, REAL(theta), REAL(ang_vel), 16) END