c
c Simulation of non-linear pendulum
c        - Euler or Runge-Kutta (2nd order usual one)
c Fortran version written by H. Nakanishi, need to be compiled with "-lpepl".
c Line 74 originally had incorrrect index; corrected to: "t1 = t(i-1)+0.5*dt"
c
	program pendulum
c
c       Declare the arrays we will need
c
	dimension th(5003),om(5003),t(5003)
c
c       Use subroutines to do the work
c
	call initialize(th,om,t,ext,dt,q,fd,dr,lsym,nsym,method)
	call calculate(th,om,t,ext,dt,q,fd,dr,n,lsym,nsym,method)
	call display(th,om,t,ext,dt,q,fd,dr,n,lsym,nsym,method)
	stop
	end
c
	subroutine initialize(th,om,t,ext,dt,q,fd,dr,lsym,nsym,method)
c
c       Initialize variables
c
        dimension th(1),om(1),t(1)
	character ans,yes
	yes='y'
	print *,'Euler(1), Euler-Cromer(2) or Runge-Kutta(3)? -> '
	read(5,*) method
	if(method.ne.1.and.method.ne.2.and.method.ne.3) then
		print *,'must select 1, 2, or 3 ..'
		stop
	endif
	print *,'initial angle, angular velocity, pendulum length?'
	read(5,*) th(1),om(1),ext
	t(1)=0
	print *,'time step, damping const, force amp, frequency?'
	read(5,*) dt,q,fd,dr
	print *,'set line, symbol?'
	read(5,14) ans
14	format(a1)
	if(ans.eq.yes) then
		print *,'lsym, nsym ? -> '
		read(5,*) lsym,nsym
	else
		lsym=-1
		nsym=1
	endif
	return
	end
c
	subroutine calculate(th,om,t,ext,dt,q,fd,dr,n,lsym,nsym,method)
c
c       Now use the Euler method or the Runge-Kutta (2nd order)
c
	dimension th(1),om(1),t(1)
	g=9.8
	period=6.2831853/sqrt(g/ext)
	nmax=5000
	do 10 i = 2,nmax
		t(i) = t(i-1)+dt
	    if(method.eq.1) then
		call dv(om(i-1),th(i-1),t(i-1),g,ext,q,fd,dr,dom,dth)
         	om(i) = om(i-1)+dt*dom
         	th(i) = th(i-1)+dt*dth
	    elseif(method.eq.2) then
		call dv(om(i-1),th(i-1),t(i-1),g,ext,q,fd,dr,dom,dth)
         	om(i) = om(i-1)+dt*dom
         	th(i) = th(i-1)+dt*om(i)
	    else
		call dv(om(i-1),th(i-1),t(i-1),g,ext,q,fd,dr,dom,dth)
         	om1 = om(i-1)+0.5*dt*dom
         	th1 = th(i-1)+0.5*dt*dth
		t1 = t(i-1)+0.5*dt
		call dv(om1,th1,t1,g,ext,q,fd,dr,dom2,dth2)
		om(i)=om(i-1)+dt*dom2
		th(i)=th(i-1)+dt*dth2
	    endif
	    if(t(i).ge.10*period) then
		n=i
		return
	    endif
10	continue
  	n=nmax
	return
	end
c
	subroutine dv(om0,th0,t0,g,ext,q,fd,dr,dom,dth)
	dth=om0
	dom=-g/ext*sin(th0)-q*om0+fd*sin(dr*t0)
	return
	end
c
	subroutine display(th,om,t,ext,dt,q,fd,dr,n,lsym,nsym,method)
c
c       First set up title and label axes for graph. Plotting is a lot
c       of work in fortran.
c       This version displays output as well as writes to a file "graph.out".
c
	dimension th(1),om(1),t(1)
	call usrmon(.true.,.false.,-0.5,9.,-0.5,12.)
	call pltlun(19,.true.,.false.)
	call pltlfn('graph.out')
	call plots
	call plot(0.,3.5,-3)
	if(method.eq.1) then
	call text(0.2,5.8,0.2,'Pendulum: Euler',0.,15,0)
	elseif(method.eq.2) then
	call text(0.2,5.8,0.2,'Pendulum: Euler-Cromer',0.,22,0)
	else
	call text(0.2,5.8,0.2,'Pendulum: Runge-Kutta2',0.,22,0)
	endif
	call text(0.2,5.5,0.2,'Angle vs Time',0.,13,0)
	call scalex(t,5.,n,1)
	call axctl(0.15,0.04,0.15,0.2,0.2,-1)
	call axisx(0.,0.,'Time (s)',-8,5.,0.,
     c  t(n+1),t(n+2),t(n+3),4)
	call axisx(0.,5.,' ',1,5.,0.,t(n+1),t(n+2),t(n+3),20)
	call scalex(th,5.,n,1)
	call axctl(0.15,0.04,0.15,0.2,0.2,2)
	call axisx(0.,0.,'Angle (radians)',15,5.,90.,
     c	th(n+1),th(n+2),th(n+3),-5)
	call axisx(5.,0.,' ',-1,5.,90.,
     c  th(n+1),th(n+2),th(n+3),-21)
	call line(t,th,n,1,lsym,nsym)
	call number(0.5,3.7,0.1,q,0.,'''q = '',f5.2')
	call number(0.5,3.9,0.1,fd,0.,'''fd= '',f5.2')
	call number(0.5,4.1,0.1,dr,0.,'''dr= '',f8.5')
	call number(0.5,4.3,0.1,ext,0.,'''ext = '',f5.2')
	call number(0.5,4.5,0.1,dt,0.,'''dt = '',f5.2')
	call number(0.5,4.7,0.1,ext,0.,'''ext = '',f5.2')
	call plot(0.,0.,999)
	return
	end

