! pendul - Program to compute the motion of a simple pendulum
! using the Euler or Verlet method

      program pendul
      integer*4 MAXnStep
      parameter( MAXnStep = 100000 )
      integer*4 method, irev, iStep, nStep, nPeriod, i
      real*8 theta0, pi, theta, omega, g_over_L, time, time_old
      real*8 tau, accel, theta_old, theta_new, AvePeriod, ErrorBar
      real*8 t_plot(MAXnStep), th_plot(MAXnStep), period(MAXnStep)

      !* Select the numerical method to use: Euler or Verlet
      write(*,*) 'Choose a numerical method 1) Euler, 2) Verlet: '
      read(*,*) method

      !* Set initial position and velocity of pendulum
      write(*,*) 'Enter initial angle (in degrees): '
      read(*,*) theta0
      pi = 3.141592654
      theta = theta0*pi/180   ! Convert angle to radians
      omega = 0.0             ! Set the initial velocity

      !* Set the physical constants and other variables
      g_over_L = 1.0          ! The constant g/L
      time = 0.0              ! Initial time
      irev = 0                ! Used to count number of reversals
      write(*,*) 'Enter time step: '
      read(*,*) tau

      !* Take one backward step to start Verlet
      accel = -g_over_L*sin(theta)    ! Gravitational acceleration
      theta_old = theta - omega*tau + 0.5*tau**2*accel

      !* Loop over desired number of steps with given time step
      !    and numerical method
      write(*,*) 'Enter number of time steps: '
      read(*,*) nStep
      do iStep=1, nStep

        !* Record angle and time for plotting
        t_plot(iStep) = time
        th_plot(iStep) = theta*180/pi   ! Convert angle to degrees
        time = time + tau

        !* Compute new position and velocity using
        !    Euler or Verlet method
        accel = -g_over_L*sin(theta)    ! Gravitational acceleration
        if( method .eq. 1 ) then
          theta_old = theta        ! Save previous angle
          theta = theta + tau*omega       ! Euler method
          omega = omega + tau*accel
        else
          theta_new = 2*theta - theta_old + accel*tau**2
          theta_old = theta        ! Verlet method
          theta = theta_new
        endif

        !* Test if the pendulum has passed through theta = 0;
        !    if yes, use time to estimate period
        if( theta*theta_old .lt. 0 ) then   ! Test position for sign change
          write(*,*) 'Turning point at time t = ', time
          if( irev .eq. 0 ) then     ! If this is the first change,
            time_old = time          ! just record the time
          else
            period(irev) = 2*(time - time_old)
            time_old = time
          endif
          irev = irev+1       ! Increment the number of reversals
        endif

      enddo
      nPeriod = irev-1        ! Number of times period is measured

      !* Estimate period of oscillation, including error bar
      AvePeriod = 0.0
      ErrorBar = 0.0
      do i=1,nPeriod
        AvePeriod = AvePeriod + period(i)
      enddo
      AvePeriod = AvePeriod/nPeriod
      do i=1,nPeriod
        ErrorBar = ErrorBar + (period(i) - AvePeriod)**2
      enddo
      ErrorBar = sqrt(ErrorBar/(nPeriod*(nPeriod-1)))
      write(*,*) 'Average period = ', AvePeriod, ' +/- ', ErrorBar

      !* Print out the plotting variables: t_plot, th_plot
      open(11,file='t_plot.txt',status='unknown')
      open(12,file='th_plot.txt',status='unknown')
      do i=1,nStep
        write(11,*) t_plot(i)
        write(12,*) th_plot(i)
      enddo
      stop
      end

!***** To plot in MATLAB; use the script below ********************
!load t_plot.txt; load th_plot.txt;
!clf;  figure(gcf);         % Clear and forward figure window
!plot(t_plot,th_plot,'+');
!xlabel('Time');  ylabel('Theta (degrees)');
!******************************************************************

