The following assignment involves writing and testing two Fortran 77 programs which use lsoda to solve ordinary differential equations. As usual, all files required by the assignment must reside in the correct places on your lnx account for the homework to be considered complete. Contact me immediately if you are having undue difficulties with any part of the homework.
Problem 1: Consider the following ODE, known as the Van der
Pol equation:
In directory /hw5/a1, write a Fortran 77 program vdp.f, with corresponding executable vdp which solves the above ODE subject to the initial conditions:
(2) | |||
(3) |
vdp must have the following usage:
usage: vdp <tmax> <u0> <du0> <epsilon> <tol> <olevel>where
Your program must be commented, and must perform rudimentary error-checking of command-line arguments: arguments should be of the proper type, and should be in the appropriate ranges as given above (as usual, you can use i4arg and r8arg to detect whether an argument is of the correct type by using default values which a user is unlikely to enter).
At requested output times, vdp must write on standard output the time, and the computed displacement and velocity of the oscillator at that time, using an output statement such as
write(*,*) t, y(1), y(2)
The requested output times, , are defined by
(4) |
(5) |
To test your implementation, code an independent residual evaluation program, chk-vdp.f--with corresponding executable chk-vdp--which applies an finite-difference approximation of (1) to the output of vdp. chk-vdp.f should be identical in construction, as well as what it inputs and outputs, to the chk-tlsoda.f example covered in class, except that chk-vdp.f is to accept a single, real*8 command-line argument, epsilon. Use the usual difference approximations for the first and second time-derivatives in (1); namely:
(6) | |||
(7) |
#!/bin/sh epsilon=1.0 vdp 10.0 0.0 1.0 $epsilon 1.0d-8 10 | nth 1 2 > vdp-out for inc in 8 4 2 1; do nth 1 2 < vdp-out | lines 1 . $inc | chk-vdp $epsilon doneOnce you are satisfied that both vdp and chk-vdp are working properly, execute the script and save the output as chk-vdp-out.
In order to get a feel for the behaviour of the oscillator, use vdp to investigate the solution of (1) for a variety of values of ( suggested), u0 ( suggested) and du0, ( suggested). When performing your studies, ensure that you specify tmax large enough to determine the long-time behaviour of the oscillator. You can use gnuplot to plot the results of your computations.
An interesting way to examine the dynamics of an oscillator is to make a phase-space plot, i.e. a parametric plot (in ) of the oscillator's velocity versus its displacement. Use gnuplot to make a single phase-space Postscript plot called vdp-phase showing the vs trajectories from the following three computations:
vdp 50.0 0.01 0.0 1.0 1.0e-8 11 vdp 50.0 1.0 -1.0 1.0 1.0e-8 11 vdp 50.0 3.0 1.0 1.0 1.0e-8 11
Using gnuplot, make a Postscript plot called vdp.ps showing the oscillator displacement versus for the following computation
vdp 100.0 0.01 0.0 10.0 1.0e-8 12
What can you say about the long-time behaviour of the oscillator as a function of and for fixed ? Answer in /hw5/a1/README.
Problem 2: Consider the following partial differential equation,
(frequently called the diffusion equation, or heat equation):
In directory /hw5/a2, write a Fortran 77 program,
diffusion.f, with corresponding executable diffusion, which
solves the above PDE using the method of lines, and lsoda.
Specifically, convert (8) into a system of
coupled ODEs by (i) introducing a regular mesh and discrete unknowns
:
(11) |
(13) | |||
(14) |
diffusion must have the following usage:
usage: diffusion <xlevel> <olevel> <tfinal> <dtout> <tol>where
For the initial conditions (9), use the following gaussian profile:
(15) | |||
(16) |
diffusion must output the approximate solution to standard output using the gnuout routine, which can be copied from phys410/hw5/diffusion/gnuout.f:
c=========================================================== c Output to standard out for subsequent plotting via c gnuplot. c=========================================================== subroutine gnuout(u,x,nx,t,stride) implicit none integer nx, stride real*8 u(nx), x(nx), t integer j do j = 1 , nx , stride write(*,*) t, x(j), u(j) end do write(*,*) return endNote that the stride argument is used to ``down-sample'' the data being written, since at high spatial resolutions, direct surface plotting via gnuplot will produce very large, mostly illegible plots. In the current case stride is defined as follows:
(17) |
Your program must be commented and must perform error-checking of command-line arguments as in Problem 1.
In developing your program, you may find it useful to use the xvs interface, the xvs visualization server, and the sdftoxvs utility program which sends .sdf files to xvs. See the Course Software page for information on these topics, as well as the Supplementary Material for Homework 5 section of the ODE Notes page.
After your program has been de-bugged to your satisfaction, use it to generate a file out8 which contains the standard output of the invocation
diffusion 8 6 0.20 0.005 1.0e-6Using gnuplot, make a parametric surface plot of this data and save it as the Postscript file out8.ps.
Finally, in hw5/a2/README, briefly discuss how you might go about verifying that your program is correct (i.e. that as and we have ).