c c Simulation of velocity vs. time for a large cannon c - Euler or Runge-Kutta (2nd or 4th order usual ones) c Program to accompany "Computational Physics" by N. Giordano and H. Nakanishi c Fortran version written by H. Nakanishi, need to be compiled with "-lpepl". c program cannon2 c c Declare the arrays we will need c dimension x(5003), y(5003) c c Use subroutines to do the work c call initialize(dt,vinit,theta,Am,lsym,nsym,method) call calculate(x,y,dt,vinit,theta,Am,n,method) call display(x,y,n,theta,Am,dt,lsym,nsym,method) stop end c subroutine initialize(dt,vinit,theta,Am,lsym,nsym,method) c c Initialize variables c character ans,yes yes='y' print *,'Euler (1) or Runge-Kutta 2nd order (2), 4th (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 velocity -> ' read(5,*) vinit print *,'time step -> ' read(5,*) dt print *,'drag/m -> ' read(5,*) Am print *,'firing angle -> ' read(5,*) theta print *,'set line, symbol?' read(5,14) ans 14 format(a1) if(ans.eq.yes) then print *,'line and symbol numbers -> ' read(5,*) lsym,nsym else lsym=-1 nsym=1 endif return end c subroutine calculate(x,y,dt,vinit,theta,Am,n,method) c c Now use the Euler method or the Runge-Kutta (2nd order) c dimension x(1),y(1) x(1)=0 y(1)=0 vx=vinit*cos(3.141592*theta/180) vy=vinit*sin(3.141592*theta/180) nmax=5000 if(method.eq.1) then do 10 i = 2,nmax call deriv(x(i-1),y(i-1),vx,vy,0,Am,dx,dy,dvx,dvy) x(i)=x(i-1)+dt*dx y(i)=y(i-1)+dt*dy vx=vx+dt*dvx vy=vy+dt*dvy if(y(i).le.0) then n=i go to 15 endif 10 continue elseif(method.eq.2) then do 30 i = 2,nmax call deriv(x(i-1),y(i-1),vx,vy,0,Am,dx,dy,dvx,dvy) x1=x(i-1)+0.5*dt*dx y1=y(i-1)+0.5*dt*dy vx1=vx+0.5*dt*dvx vy1=vy+0.5*dt*dvy call deriv(x1,y1,vx1,vy1,0,Am,dx2,dy2,dvx2,dvy2) x(i)=x(i-1)+dt*dx2 y(i)=y(i-1)+dt*dy2 vx=vx+dt*dvx2 vy=vy+dt*dvy2 if(y(i).le.0) then n=i go to 15 endif 30 continue else do 40 i = 2,nmax call deriv(x(i-1),y(i-1),vx,vy,0,Am,dx,dy,dvx,dvy) x1=x(i-1)+0.5*dt*dx y1=y(i-1)+0.5*dt*dy vx1=vx+0.5*dt*dvx vy1=vy+0.5*dt*dvy call deriv(x1,y1,vx1,vy1,0,Am,dx2,dy2,dvx2,dvy2) x2=x(i-1)+0.5*dt*dx2 y2=y(i-1)+0.5*dt*dy2 vx2=vx+0.5*dt*dvx2 vy2=vy+0.5*dt*dvy2 call deriv(x2,y2,vx2,vy2,0,Am,dx3,dy3,dvx3,dvy3) x3=x(i-1)+dt*dx3 y3=y(i-1)+dt*dy3 vx3=vx+dt*dvx3 vy3=vy+dt*dvy3 call deriv(x3,y3,vx3,vy3,0,Am,dx4,dy4,dvx4,dvy4) x(i)=x(i-1)+0.16666667*dt*(dx+2*dx2+2*dx3+dx4) y(i)=y(i-1)+0.16666667*dt*(dy+2*dy2+2*dy3+dy4) vx=vx+0.16666667*dt*(dvx+2*dvx2+2*dvx3+dvx4) vy=vy+0.16666667*dt*(dvy+2*dvy2+2*dvy3+dvy4) if(y(i).le.0) then n=i go to 15 endif 40 continue endif n=nmax 15 a=-y(n)/y(n-1) x(n)=(x(n)+a*x(n-1))/(1+a) y(n)=0 return end c subroutine deriv(x0,y0,vx0,vy0,t0,Am,dx,dy,dvx,dvy) dx=vx0 dy=vy0 f=Am*sqrt(vx0**2+vy0**2) dvx=-f*vx0 dvy=-f*vy0-9.8 return end c subroutine display(x,y,nmax,theta,Am,dt,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 x(1),y(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,'Cannonball in air: Euler',0.,24,0) elseif(method.eq.2) then call text(0.2,5.8,0.2,'Cannonball in air: Runge-Kutta2',0.,31,0) else call text(0.2,5.8,0.2,'Cannonball in air: Runge-Kutta4',0.,31,0) endif call text(0.2,5.5,0.2,'Height vs Distance',0.,20,0) call scalex(x,5.,nmax,1) call axctl(0.15,0.04,0.15,0.2,0.2,-1) call axisx(0.,0.,'Distance (m)',-12,5.,0., c x(nmax+1),x(nmax+2),x(nmax+3),4) call axisx(0.,5.,' ',1,5.,0., c x(nmax+1),x(nmax+2),x(nmax+3),20) call scalex(y,5.,nmax,1) call axctl(0.15,0.04,0.15,0.2,0.2,-1) call axisx(0.,0.,'Height (m)',11,5.,90., c y(nmax+1),y(nmax+2),y(nmax+3),-5) call axisx(5.,0.,' ',-1,5.,90., c y(nmax+1),y(nmax+2),y(nmax+3),-21) call line(x,y,nmax,1,lsym,nsym) call number(1.5,2.0,0.2,theta,0.,'''theta = '',f5.2') call number(1.5,2.3,0.2,Am,0.,'''A_m= '',1pe8.2') call number(1.5,2.6,0.2,dt,0.,'''dt = '',f5.2') call plot(0.,0.,999) return end