#!/bin/sh
# Do a little magic to run perl from anywhere in your path.

lines=`cat $0 | wc -l`
lines=`expr $lines - 10`
tail -$lines $0 > /tmp/meshtvperl$$
echo "__END__" >> /tmp/meshtvperl$$
echo "$0 $*" >> /tmp/meshtvperl$$
exec perl /tmp/meshtvperl$$ $0 ${1+"$@"}

unlink $0;
$0 = shift @ARGV;

###############################################################################
#
#         Run the MeshTV CLI on various architectures
#
# Programmer:  Sean Ahern (adopted from a script that Jeremy Meredith wrote)
# Date      :  Aug 13, 1999
#
# Modifications:
#
#    Jeremy Meredith, Thu Aug 26 13:11:33 PDT 1999
#    Added check for -nowin meshtvx option on IBM's to prevent interactivity.
#
#    Jeremy Meredith, Fri Mar 24 11:42:48 PST 2000
#    Added partition argument and ability to use prun instead of mpirun.
#
#    Brad Whitlock, Mon Mar 27 17:26:31 PST 2000
#    Added logic to handle the TFLOPS O/S.
#
#    Lisa J. Roberts, Fri May 12 15:23:29 PDT 2000
#    Changed luke to oak, since luke no longer exists. [HYPer01812]
#    I also appended our path info to the user's path so more
#    machines can find Netscape when they need it. [HYPer01801]
#
#    Eric Brugger, Fri Sep  1 16:16:49 PDT 2000
#    I added "-DFS" to the psub command line so that jobs running in batch
#    can access dfs.
#
###############################################################################

# If we're running in parallel, and using psub, we're gonna need to know how 
# to run xterm.
chomp( $xtermcmd = `which xterm`);
$xtermgone = $?;

# Set a secure and reasonable path
$ENV{PATH} = join ':' , ("$ENV{PATH}","/bin","/usr/bin","/usr/sbin",
                         "/usr/local/bin", "/usr/bsd","/usr/ucb" );

# Determine OS and set binary directory "meshtvbindir"

# set base directory
chomp( $progdir = `dirname $0` );
chomp( $cwd = `pwd`        );

for ($progdir) {
    /^\//  && do { $tmpdir = $progdir; last; }; # starts with `/'
    /^\.$/ && do { $tmpdir = $cwd; last; };     # is exactly  `.'
    $tmpdir = "$cwd/$progdir";
}
chomp( $meshtvdir = `dirname $tmpdir` );

$use_psub = 0;
$use_yod = 0;
$meshtvbindir = "unsupported";
chomp( $os = `uname -s` );
$os =~ tr/[A-Z]/[a-z]/;
for ($os) {
    /irix/ && do {
        $version = `uname -r`;
        $version =~ s/(^[456])\..*/irix$1/ ;
        for ($version) {
            /irix4/ && do {
                $meshtvbindir = "$meshtvdir/bin/sgi-irix4-mips";
                last;
            };
            /irix5/ && do {
                $meshtvbindir = "$meshtvdir/bin/sgi-irix5-mips";
                last;
            };
            /irix6/ && do {
                $meshtvbindir = "$meshtvdir/bin/sgi-irix6-mips2";
                last;
            };
        }
        last;
    };
    /sunos/ && do {
        chomp( $mach    = `uname -m` );
        chomp( $version = `uname -r` );
        $version =~ s/([45])\..*/sunos$1/ ;
        if ($mach =~ /^sun4/) {
            $meshtvbindir = "$meshtvdir/bin/sun4-$version-sparc";
        }
        last;
    };
    /hp-ux/ && do {
        if (`uname -m` =~ /9000\/[78]/) {
            $meshtvbindir = "$meshtvdir/bin/hp-hpux-pa";
        }
        last;
    };
    /aix/ && do {
        $meshtvbindir = "$meshtvdir/bin/ibm-aix-pwr";
        $use_psub = 1;
        last;
    };
    /osf/ && do {
        $meshtvbindir = "$meshtvdir/bin/dec-osf1-alpha";
        last;
    };
    /linux/ && do {
        $meshtvbindir = "$meshtvdir/bin/linux";
        last;
    };
    /tflops/ && do {
        $meshtvbindir = "$meshtvdir/bin/intel-tflops-ppro";
        $use_yod = 1;
        last;
    };
}

# Set some defaults.
$parallel_usage = "
    Optional parallel arguments:
        -np #           The number of processors to use (required)
";
if (! $use_psub && ! $use_yod)
{
    $parallel_usage .= "
        -p partition    Partition in which to run (when launching using prun)
";
}
if ($use_psub)
{
    $parallel_usage .= "
        -r name         The parallel job name (optional)
        -c pool         Constraints used to determine the set of hosts on
                            which the job must run (optional)
        -b bank         Bank from which permitted resources are to be
                            drawn (optional)
        -tM time        Maximum job run time (optional)
        -a acct         Account that is to be charged (optional)
";
}

$usage = "
USAGE:
    meshtvx [parallel arguments] [-geometry spec] [-banner string] [-nowin]
            [-n] [-noinfo] [-nowarn] [-q] [-ppm rootname] [-ps rootname] [-rgb
            rootname] [-rps rootname] [-s filename] [-tif rootname] [-res #]
            [Silo_file] [initfile]

    Normal arguments:
        -nowin              Do not open visualization windows
        -n                  End the prompt with a newline character
        -noinfo             Do not output MeshTV informational messages
        -nowarn             Do not output MeshTV warning messages
        -q                  Quiet mode.  Equivalent to \"-noinfo -nowarn\"
        -ppm rootname       Write plots in PPM format to rootname####.ppm
        -tif rootname       Write plots in TIFF format to rootname####.tif
        -rgb rootname       Write plots in RGB format to rootname####.rgb
        -ps rootname        Write plots in Postscript to rootname####.ps
        -rps rootname       Write plots in Raster Postscript to rootname####.ps
        -banner string      The banner string to use on Postscript output
        -res #              The x/y resolution for saved and printed images
        -s filename         A script from which to execute MeshTV commands
        -geometry spec      What portion of the screen to use.  This is a
                            standard X Windows geometry specification
        Silo_file           Silo file to open upon startup
        initfile            A MeshTV init file, similar to .meshtvinit
";

$parallel = 0;
$want_version = 0;
$np   = 0;
$name = "meshtvx";
$bank = "";
$time = "";
$acct = "";
($node) = split /\./,`hostname`;
($sector = $node) =~ tr/[0-9]//d;
$pool = "pbatch,$sector";
$part = "";

# Parse the arguments
@meshtvargs = ();
while ($arg = shift @ARGV) {
    if    ($arg eq "-np")   { $np   = shift; $parallel = 1; }
    elsif ($arg eq "-r" )   { $name = shift; $name_set = 1; }
    elsif ($arg eq "-c" )   { $pool = shift; $pool_set = 1; }
    elsif ($arg eq "-b" )   { $bank = shift; $bank_set = 1; }
    elsif ($arg eq "-tM")   { $time = shift; $time_set = 1; }
    elsif ($arg eq "-a" )   { $acct = shift; $acct_set = 1; }
    elsif ($arg eq "-p" )   { $part = shift; $part_set = 1; }
    elsif ($arg eq "-help") { print "$usage\n$parallel_usage\n"; exit(0); }
    elsif ($arg eq "-version") { $want_version = 1; }
    else                    { push @meshtvargs, $arg; }
}

# Check for sanity
if ((!$parallel)
    and ($name_set or $pool_set or $bank_set or $time_set or $acct_set or $part_set)
   )
{
    print STDERR <<"EOF";
You specified a parallel argument without using -np to specify the number of
processors.  Please add an -np argument.
EOF
    print STDERR $usage;
    print STDERR $parallel_usage;
    exit(1);
}

if (($parallel) and ($np < 2))
{
    print STDERR <<"EOF";
You must specify more than one processor to execute parallel meshtvx.
You specified \"$np\" processors.
EOF
    exit 1;
}

# Check for errors
if ($meshtvbindir eq "unsupported")
{
    print STDERR <<"EOF";
This hardware platform is not supported by meshtvx.
EOF
    exit 1;
}

if (! -d $meshtvbindir)
{
    print STDERR <<"EOF";
The executables for this hardware platform have not been installed.
EOF
    exit 1;
}


# Set required environment variables
$ENV{TRAP_FPE} = "";
$ENV{MESHTVHOME}     = "$meshtvdir";
$ENV{MESHTVHELPHOME} = "$meshtvdir/help";
$ENV{MESHTVURLHOME}  = "/usr/lib/meshtv/";
#    gethostbyname("oak.scf.cln") ? "http://oak.scf.cln/" : "http://www.llnl.gov/";

# Find the executables
$cli_name = "meshtvx";
$cli_name .= "p" if ($parallel);
@cli = grep(/$cli_name[\d\.]+$/,<$meshtvbindir/$cli_name*>);

$msg = "";
if (scalar(@cli) == 0)
{
    $msg = "parallel " if ($parallel);
    print STDERR <<"EOF";
No versions of ${msg}meshtvx have been installed for this hardware platform.
EOF
    exit(1);
}

@versions = @cli;
@versions = grep( s/^.*$cli_name//, @versions);
$max = 0;
foreach $num (@versions)
{
    $version = $num;
    $num =~ s/(\d\.\d)\.(\d)/$1$2/;
    if ($num > $max)
    {
        $max = $num;
        $max_version = $version;
    }
}

if ($want_version)
{
    print STDERR <<"EOF";
The latest version of meshtvx installed on this platform is $max_version.
EOF
    exit(0);
}

@meshtvxcmd = ("$meshtvbindir/$cli_name$max_version",
              @meshtvargs);

# Run it!
if ($parallel)
{
    push(@meshtvxcmd,"-n");

    if ($use_psub) {
        @psubcmd = ("psub");
        push @psubcmd, "-x";
        push @psubcmd, "-DFS";
        push @psubcmd, "-ln", int(($np+3)/4);
        push @psubcmd, "-g",  $np;
        push @psubcmd, "-r",  $name  if $name;
        push @psubcmd, "-c",  $pool  if $pool;
        push @psubcmd, "-b",  $bank  if $bank;
        push @psubcmd, "-tM", $time  if $time;
        push @psubcmd, "-a",  $acct  if $acct;

        $nowin = 0;
        for (@meshtvargs)
        {
            $nowin=1 if (/^-nowin$/);
        }
        
        if ($nowin)
        {
            push @psubcmd, "-i", "cd $cwd ; @meshtvxcmd";
        }
        else
        {
            die "Could not find `xterm' in your path.\n" if ($xtermgone);
            push @psubcmd, "-i", "cd $cwd ; setenv DISPLAY $ENV{DISPLAY} ; ".
                                 "$xtermcmd -sl 1000 -e @meshtvxcmd";
        }

        @psubnicecmd = @psubcmd;
        push @psubnicecmd, ("\"".(pop @psubnicecmd)."\"");
        print "Running: @psubnicecmd\n";
        exec @psubcmd or die "Can't execute psub: $!\n";
    }
    elsif ($part) {
        @pruncmd = ("prun");
        push @pruncmd,"-n",$np;
        push @pruncmd,"-p",$part;
        push @pruncmd,@meshtvxcmd;

        @printcmd = @meshtvxcmd;
        chomp($printcmd[0] = `basename $printcmd[0]`);
        print "Running: prun -n $np -p $part @printcmd\n";
        exec @pruncmd or die "Can't execute prun: $!\n";
    }
    elsif ($use_yod) {
        @yodcmd = ("/cougar/bin/yod");
        push @yodcmd,"-sz",$np;
        push @yodcmd,@meshtvxcmd;

        @printcmd = @meshtvxcmd;
        chomp($printcmd[0] = `basename $printcmd[0]`);
        print "Running: yod -sz $np @printcmd\n";
        exec @yodcmd or die "Can't execute yod: $!\n";
    }
    else {
        @mpiruncmd = ("mpirun");
        push @mpiruncmd,"-np",$np;
        push @mpiruncmd,@meshtvxcmd;

        @printcmd = @meshtvxcmd;
        chomp($printcmd[0] = `basename $printcmd[0]`);
        print "Running: mpirun -np $np @printcmd\n";
        exec @mpiruncmd or die "Can't execute mpirun: $!\n";
    }
} else {
    @printcmd = @meshtvxcmd;
    chomp($printcmd[0] = `basename $printcmd[0]`);
    print "Running: @printcmd\n";
    exec @meshtvxcmd or die "Can't execute meshtvx: $!\n";
}
