CODING SUGGESTIONS
In scientific computing, CLARITY and EFFICIENCY are paramount !
so keep it simple, understandable, and efficient !
Use double precision for all real variables (not 'float').
Use natural indexing, short and meaningful variable names,
as close to those used in the numerical scheme as possible.
e.g. running index for space: i or j or k, running index for time: n
PLEASE USE the same names for routines and variables as in the algorith presented in class
Natural indexing and array dimensions for a mesh of M control volumes are:
x(0:M+1), with x(0)=a and x(M+1)=b the boundaries;
U(0:M+1), with U(0) and U(M+1) the boundary values at a and b;
F(1:M+1), with F(1)=F½ and F(M+1)=FM+½ the boundary fluxes at a and b.
Efficiency: Minimize operations (without sacrificing clarity), e.g.:
* since M+1 is used repeatedly, set Mp1=M+1 and use Mp1 everafter.
* always evaluate polynomials in nested form (Horner's Rule),
e.g. ax²+bx+c = c + x*( b + a*x )
* x*x*x is MUCH cheaper than x3 (even worse would be x3.0 which forces exp and log evaluations!)
* Minimize storage: only x, F, U need to be indexed as (spatial) arrays.
Trapezoidal Rule Quadrature:
Here is an efficient implementation ( for our mesh! ) in Fortran,
which assumes the U array is indexed as U(0),U(1), ..., U(M+1).
(check that it is correct!)
double precision FUNCTION TrapzRule( M, Dx, U )
dimension U(0:M+1)
Area = ( U(0) - U(1) - U(M) + U(M+1) )/4
DO i = 1,M
Area = Area + U(i)
ENDDO
TrapzRule = Area * Dx
end
Code outline for time-stepping scheme:
declare variables, dimension arrays
read data file: MM, tend, t0, dtout, factor, D, a, b
dx = 1.0/MM ; M = (b-a)*MM !! =(b-a)/dx
dtEXPL = dx*dx/(2*D) ; dt = factor*dtEXPL
call MESH(...)
!-----initialize-----!
nsteps = 0 ; time = 0.0 ; tout = dtout ; MaxSteps=INT(tend/dt)+1
call INIT(...)
call OUTPUT(...) !!profile at time=0
!-----begin timestepping-----!
DO nsteps = 1, MaxSteps
call FLUX(...)
call PDE(...)
time = nsteps*dt !! =time + dt
if( time >= tout ) then
call OUTPUT(...)
tout = tout + dtout
endif
ENDDO
!-----end of timestepping-----!
print: 'DONE, exiting at t=', time ,' after ', nsteps ,' steps'
PLEASE USE the above names for routines and variables, as in the algorith presented in class.
Output for plotting:
* Lines starting with # are comments for gnuplot (and most other plotters).
* Blank line starts a new curve.
* It is best to print run-time info to stdout (to screen or redirect to a file: a.out < dat > o.out ),
and to print values for plotting in separate file(s)
* I find it convenient to name all output files as "o.name", so profiles in o.prof, histories in o.hist, etc.
* Profiles are pairs: x(i), U(i), i=0,...,M+1, at specific desired times, printed in 2 columns.
* You can print all profiles in one file, say o.prof, separated by blank line(s),
each preceded by a comment line specifying the time of that profile. But when plotted, all will be of the same color.
* Or each in a separate file, e.g. o.prof0, o.prof2, o.prof4, o.prof6, which you can gnuplot with:
plot "o.prof0" u 1:2 t 'time=0' w lines lt -1 lw 2, \
"o.prof2" u 1:2 t 'time=2' w lines lt 2 lw 3, \
"o.prof4" u 1:2 t 'time=4' w lines lt 3 lw 3, \
"o.prof6" u 1:2 t 'time=6' w lines lt 1 lw 3
each of different color, and with a tag, much nicer!
Caution: Do not go overboard trying to code up output at all these times!
just make a run for each with appropriate parameters (tend, dtout) and rename the file!
* See Gnuplot links on main page for how to print, etc.