#! /bin/sh

############################################################
# This shell script is a "front-end" to 2body which 
# expedites the analysis of the results from that code,
# including the generation of Postscript plots of the 
# particle position, d(energy), d(angular momentum) as a 
# function of time using gnuplot.
#
# The script is also intended as a general illustration of 
# shell programming.  A key idea here is that many things 
# which are cumbersome in Fortran (or C, or C++) 
# (such as file manipulation, and piecing together different 
# commands) are easily accomplished with a script.
#
# See the Unix Programming Environment by Kernighan and Pike
# for classic documentation on shell programming and more!
############################################################

############################################################
# Note that the first line of this file is very important.
# It allows Unix to identify the contents of the file as 
# a shell script ('/bin/sh' is the shell executable on 
# ALL non-brain-dead Unix systems), so that, provided the 
# file is made executable and resides in a directory in 
# the current path, typing the name of the file will 
# result in execution of the script.  The space between 
# the '#!' and '/bin/sh'is recommended for maximum script 
# portability. 
# 
# A variant initial line, particularly useful for script 
# development is 
#
# #! /bin/sh -x
# 
# The '-x' flag enables tracing, so that assignments of 
# shell variables, execution of commands etc. will be 
# echoed to standard error.
############################################################

############################################################
# ASSIGNMENT STATEMENTS 
#
# The following code assigns some default values to some 
# shell variables. 
#
# NOTE: There can be *no* white
# space around the '=' in an assignment statement. If, 
# for example you type 
# 
# tmax = 5.0
#
# then, when you execute the script, you will get the 
# cryptic error message
#
# tmax: Not found
#
# since the shell will be interpreting the line as the 
# *command* 'tmax' with arguments '= 5.0'.
############################################################
tmax=5.0
dt=0.05
tol=1.0d-6

############################################################
# FUNCTIONS
#
# Usage function (subroutine).  Illustrates one way to 
# "do usage" in shell script (using 'cat' plus a 
# "here document"), as well as the useful "here document" 
# construction.   
#
# Here documents can be used anywhere 
# in a shell script (and in C-shell, Korn-shell, perl etc.
# script) to provide "in-place" input for the standard input 
# of a command.  You can refer to the man page on 'sh'
# for full details, but the idea and mechanics are 
# simple.  To provide "in-place" input to an arbitrary 
# command, append '<<END' after the command name and 
# all arguments.  Be certain that there is no white 
# space between the '<<' and 'END' or after 'END'.
# Subsequent lines are then the standard input to 
# the command.  A line which *exactly* matches 
# the string 'END' (i.e. 'grep ^END$' succeeds) 
# signals end-of-file (so be sure you have such a line
# in your script!).  Again, beware of leading or trailing 
# white space in the end-of-file marker.  Finally, note that 
# the string'END' is arbitrary---you can use essentially any 
# string you wish (but be sure to use the identical string in 
# both contexts)---'END' is simply my convention.
#
# Here documents wouldn't be half as interesting if 
# it weren't for the fact that they are partially interpreted 
# by the shell.  In particular, shell variables are evaluated
# as are `command [arguments]` constructs (recall that 
# we can view such constructs as "active expressions" of 
# their standard outputs).  Thus, when the Usage subroutine
# executes `date` will be replaced by the output from the 
# 'date' command and  $tol will be replaced with the 
# specific value assigned above.
############################################################
Usage() {
cat<<END
`date`
usage: Doit <y0> [<tol>]

       Default tol: $tol

       y0 = 1.0 will produce circular orbit.

       To enable automatic previewing of Postscript files
       set GV environment variable to any non-blank
       value, e.g.
   
       setenv GV on
END
############################################################
# Exit with non-zero status (failure).
############################################################
exit 1
}

############################################################
# Subroutine (fcn) to produce postscript version of 
# gnuplot plot of data stored in file $1.  Postscript 
# file will be called $1.ps.  If optional second argument
# is supplied, the resulting Postscript file will be 
# 'gv'ed.   Again, note use of "here document";
# indentation of "here document" is strictly for readability.
############################################################
gnuplot_it(){
gnuplot<<END
   set terminal postscript portrait
   set size 0.760,1.0
   set xlabel "x"
   set ylabel "$1"
   set output "$1.ps"
   plot "$1"
   quit
END

############################################################
# IF STATEMENTS
#
# The following is shell-mnemonic for "if the second 
# argument exists".  Note that the shell 'if' statement
# is of the form
#
# if list then list [ elif list then list ] ... [ else list ] fi
#
# where a 'list' is a sequence of pipelines separated by ;, 
# &, # &&, or ||, and optionally terminated by ; or &.  
# 'list' is executed, and if it returns a zero exit 
# status (normal return), the 'list' following 'then' 
# is executed, otherwise the 'list' following 'elif' 
# is executed---if *it* returns a zero exit status, the 
# 'list' following the next 'then' is executed etc. 
# 
# A particularly useful command to use with a shell 'if'
# is 'test', which has usage
# 
# test expr 
#
# or 
# 
# [ expr ]
#
# Note that '[' and ']' really ARE commands on a Unix system.
# (Try 'which \[').  Both forms of the command evaluate 
# 'expr' (which can contain various logical operators 
# and tests---see 'man test' for more information) as 
# a Boolean, returning 0 if the value is true and non-zero
# otherwise.
############################################################

if test "${2}undefined" != undefined; then
############################################################
# Illustrates alternate (and less portable, so it is 
# claimed) form of 'test'
############################################################
   if [ -f $1.ps ]; then
      (gv $1.ps) &
   else
       echo "gnuplot_it: $f.ps does not exist"
   fi
fi
}

############################################################
# ARGUMENT HANDLING and CASE STATEMENT
# 
# '$#' is a special shell variable which evaluates to 
# the number of arguments supplied to the script.  Each
# clause in a case statment is of the form
#
# pattern [ | pattern ]...)  list;;
# 
# where each pattern is used for 'grep-style' pattern
# matching against the case variable.  In this case 
# we simply match against valid numbers of arguments 
# (1, 2 or 3), but note that the pattern-matching basis
# of the case statement makes it a particularly powerful
# and useful construct. Commands may be separated by 
# semicolons and/or new-lines. '*)' is a mnemonic for 
# 'default clause' and must come LAST in the case 
# enumeration, since matching is done clause by 
# clause until a match is found. 
#

# Note that arguments to the script are available in 
# the special variables '1, 2, 3 ...'---i.e.  
# 
# y0=$1 
#
# assigns the first argument supplied to the script to
# the shell variable 'y0' (The special vbl.
# '0' stores the name of the script).  Also note 
# the mnemonic typified by
#
# tol=${2-$tol}
#
# which reads "assign the second script argument to tol,
# with a default value of $tol should the argument not 
# exist".
############################################################
case $# in
1|2) y0=$1; tol=${2-$tol};;
*) Usage;;
esac
############################################################
# Make sure the program has been compiled.
############################################################
make -f Makefile 2body
############################################################
# Create a 'tag' which identifies the computation (encodes 
# 'y0' and 'tol'), and use it to create the name of the 
# file to which '2body' output will be directed.  Note 
# that the script does NOT completely clean up after itself 
# in the sense that the output file 'oute_...' is not 
# removed.
############################################################
tag="$y0"_"$tol"
ofile=oute_"$tag"

############################################################
# Run the program and save the output in $ofile.
############################################################
2body 0.0 $y0 1.0 0.0 $tmax $dt $tol > $ofile

############################################################
# Use 'nth' to create two column data files for as follows
#
#       xcyc_$tag:  xc   yc   
#       xc_$tag:    t    xc  
#       yc_$tag:    t    yc   
#       dEtot_$tag  t    dEtot
#       dJtot_$tag  t    JEtot
############################################################
nth 2 3 < $ofile > xcyc_$tag
nth 1 2 < $ofile > xc_$tag
nth 1 3 < $ofile > yc_$tag
nth 1 4 < $ofile > dEtot_$tag
nth 1 5 < $ofile > dJtot_$tag

############################################################
# FOR LOOPS
#
# General form:
#
# for name [ in word ... ] do list done
#
# In the case below, the shell variable 'f' takes on,
# successively, the values, xcyc_$tag, xc_$tag, ... 
#
# Note the semi-colon between the iteration values and the 
# 'do' keyword (a new-line will also work), and that 'done' 
# terminates the loop.
############################################################
for f in xcyc_$tag xc_$tag yc_$tag dEtot_$tag dJtot_$tag; do
############################################################
#  Shell scripts inherit all environment variables, such 
#  as 'GV'.  If 'GV' has not been set in 
#  the invoking environment, '$GV' will evaluate to
#  the null string.
############################################################
   gnuplot_it $f $GV
   /bin/rm $f
done
/bin/ls -l *$tag*.ps

############################################################
# Normal exit (success)
############################################################
exit 0