#!/usr/bin/perl -w
##!/usr/products/perl/IRIX-6/v5_006_1a/bin/perl -w

# v. 0.1 created by L.Dudko (dudko@lev.art.ru)
# v. 0.2  19.02.2002
# v. 0.3  06.03.2002
# v. 0.5  23.06.2003 PBS/LSF parallel runs
# v. 1.0  08.11.2005 first production version
# v. 1.1  19.09.2006 report functionality is added.
# v. 1.2  21.09.2006 a bug with the 'max' option fixed

use Getopt::Long;
use File::Path;
use File::Copy;

help() unless (@ARGV or !-e "results/batch.dat" );

#####################################################################################
# Take the input options
GetOptions(
           "h",        \$opt_h,                # short help
           "help",     \$longhelp,             # long help
           "lcs",      \$lcs,                  # list cross sections
           "d=s",      \$opt_d,                # set working directory name (insted of results)
           "b=s",      \$opt_b,                # set batch file name (instead of batch.dat)
           "run:s",    \$run,                  # run production (main option)
           "show:s",   \$show,                 # run production (main option)
           "proc=s",   \$proc,                 # set a partucular subprocess set
           "add:s" =>  \$ses2bat,              # add current session.dat to batch.dat
           "nses=i",   \$insession,            # set the initial number for prt
           "ginv",     \$ginv,                 # set gauge invarian width option
           "old",      \$oldf,                 # generate event in old style
           "nevnt=s",  \$nevnt,                # set the full number of events
           "call=s",   \$ncall,                # set the number of calls
           "kfactor=s",\$kfactor,              # scale cross section in files from "files"
           "files",    \$files,                # set all file names for the previous option
           "pbs:s",    \$pbs,                  # batch system options
           "lsf:s",    \$lsf,                  # batch system options
           "combine",  \$opt_combine,          # batch system options
           "nocombine",\$opt_nocombine         # batch system options
           );

###################################################################################################
# Set global variables
  my $fileses='session.dat';
  my $filebat='batch.dat';
  my $Nproc = 0;
  my $Nproc_current = 0;
  my $Nsession = 1;

###################################################################################################
# Change cross section values in event files according to kfactor.
# The file names are taken from the hash @ARGV
  change_cs(@ARGV) if (defined $kfactor && defined $files);

###################################################################################################
# List cross section values from protocol files (in the "prt" format).
# The file names are taken from the hash @ARGV
  list_prt(@ARGV) if defined $lcs;

###################################################################################################
# Use "results" or another defined (-d dir) directory for the
# numerical calculations. The n_comphep file must be there.
  $opt_d="results" unless defined $opt_d;
  chdir $opt_d or die "There are no $opt_d dir: $!\n";

###################################################################################################
# change default name of the batch file
  $filebat=$opt_b if defined $opt_b;

###################################################################################################
# Print the list of available processes in the
# n_comphep generator in the directory [dir] (or results).
  list_batch() if defined $show;

###################################################################################################
# Print help message
  if ($opt_h or $longhelp) {
    help();
    exit(0);
  }

###################################################################################################
# remove LOCK file if it exists
  if (-e "LOCK") {
    unlink "LOCK";
  }

###################################################################################################
# Set event numbers in each subprocesses according their contribution
# to the full cross section. The only input parameter is the full
# number of events requested
replace_nevnt(@ARGV) if defined $nevnt;

###################################################################################################
# Set event numbers in each subprocesses according their contribution
# to the full cross section. The only input parameter is the full
# number of events requested
replace_calls(@ARGV) if defined $ncall;

###################################################################################################
# check whether numerical comphep exists
  if (!-e "./n_comphep") {
    print "
    First of all you have to create the n_comphep generator
    in directory $opt_d. Use comphep symbolic part to do that.\n\n";
    exit(0);
  }

###################################################################################################
# Parameters from the exist session.dat file will keep
# in new batch.dat file. The current session number will
# set from the exist session.dat file or to unit if it is absent.
  old_ses($fileses) if -s $fileses;

###################################################################################################
# Create batch.dat file in [dir] for the all available processes
# if it is absent.
  create_batch_dat() if !-s $filebat;

###################################################################################################
# With the option --add [file] include the parameters from session.dat (or [file])
# to the existed batch.dat file.
  if (defined $ses2bat) {
    old_ses($ses2bat) unless ($ses2bat eq $fileses or $ses2bat eq "")
  }

###################################################################################################
# Combine the results of previous calculations from the temporary PBS directories (this option
# is needed only if nocombine option was used before)
  combine() if defined $opt_combine;

###################################################################################################
# Launch n_comphep in the butch mode
  run() if defined $run;
  exit(0);

###################################################################################################
###################################################################################################
###################################################################################################
# working routines
sub old_ses {
  local $/="\n#";
  open(SES,"<$_[0]") or die "there are no $_[0] in $opt_d ($!)";
  @old_session = <SES>;

# Take the session number from the session.dat file
  if ($_[0] eq $fileses) {
    $old_session[2] =~/\s(\d+)\s/g;
    $Nsession=$1;
  }
 close SES;

# Add parameters from session.dat (or --add [file]) file to batch.dat file
  if (defined $ses2bat and -e $filebat and ($_[0] eq $ses2bat or $ses2bat eq "")) {
    open(BATCH, "+<$filebat") or die "Can't open $filebat for read/write: $!\n";
    local $/="++++++++++++++\n";
    my $tmp = "";
    while (<BATCH>) {
      @blocks = split(/\n#/);
      $blocks[1] =~/\s(\d+)\s/g;
      $Nproc_current = $1;

      if ($old_session[1] eq  $blocks[1]."\n#") {
        $tmp .= join("",@old_session)."++++++++++++++\n";
        print "          The exist $ses2bat file is included to
        batch.dat file for the process $Nproc_current.\n"
      }
      else {
        $tmp .= $_
      }
    }
    seek(BATCH,0,0);
    print BATCH $tmp;
    truncate (BATCH,tell(BATCH));
    close BATCH;
  }
}

###################################################################################################
sub create_batch_dat {
  open(BATCH, "+>$filebat") or die "Can't open $filebat for read/write: $!\n";
  system ("./n_comphep", "-blind", "}}9}");
  die "Can't run n_comphep:$@" if $@;
  my $string="}";
  print "You can calculate the processes as follow:\n";
  $/="\n#";
  for (;;) {
    open(SES,"<$fileses") or die "there are no session.dat in $opt_d ($!)";
    @block = <SES>;
    $block[1] =~/\s(\d+)\s/g;
    $Nproc_current = $1;
    if ($Nproc_current > $Nproc+1) {
      $string=$string.")";
      goto COMP;
    }
    last if $Nproc_current == $Nproc;

    $Nproc=$Nproc_current;
    if ($old_session[1] and $old_session[1] eq $block[1]) {
      print BATCH @old_session;
      print "
   The exist session.dat file parameters are included to new
   batch.dat file for the process $Nproc_current.\n"
    }
    else {
      print BATCH @block
    }
    print BATCH "++++++++++++++\n";
    $block[1]=~ s/(\n\#)/\n/;
    print $block[1];
    close(SES);
    $string=$string."]";
COMP: system ("./n_comphep", "-blind", "$string.'}9}'");
    die "Can't run n_comphep:$@" if $@;
  }
  print "File results/batch.dat is created.\n";
  close BATCH;
}

###################################################################################################
sub run {
# Fill the steps to run from input options
  if ($run eq "") {
    $run_p{"vegas"} = 1;
    $run_p{"max"}   = 1;
    $run_p{"evnt"}  = 1;
  }
  foreach (split(/,/,$run)) {
    $run_p{$_} = 1;
  }

  my $nginv="";
  $nginv="}}{" if defined $ginv;

  my $noldf="";
  $noldf="]" if defined $oldf;

  my $batch_options='';
  my $comphep='';
  $comphep="COMPHEP=".$ENV{"COMPHEP"}." \n export COMPHEP\n" if defined $ENV{"COMPHEP"};
  print "$comphep\n";

# Set the PBS (LSF) run script
  if (defined $pbs or defined $lsf ) {
    my ($vegas,$max,$event)=('','','');
    $vegas = '#' if !defined $run_p{"vegas"};
    $max   = '#' if !defined $run_p{"max"};
    $event = '#' if !defined $run_p{"evnt"};

    $count = 0;
    if (defined $pbs) {
      $batch_options = qq~
#PBS -I
##PBS -l nodes=1:farm
~;
      $pbs eq '' ? $b_prefix = "qsub" : $b_prefix = $pbs;
    }
    elsif (defined $lsf) {
      $batch_options = qq~
#LSF -I
~;
      $lsf eq '' ? $b_prefix = "bsub" : $b_prefix = $lsf;
    }

    $shell_scrpt=qq~
#!/bin/sh
$batch_options
$comphep
${vegas}./n_comphep -blind ]]]]]$nginv]]]]}]]]}9}
${max}./n_comphep -blind ]]]]]$nginv]]]]}]]]]]]]}]]]]}]]]}9}
${event}./n_comphep -blind ]]]]]$nginv]]]]}]]]]]]]}]]}9}
~;
  }

  local $/="++++++++++++++\n";
  open(BATCH, "+<$filebat") or die "Can't open $filebat for read: $!\n";
  my @batch = <BATCH>;
  close BATCH;

# Set the processes to run from the input options
  if (defined $proc) {
    @proc_n = proc_nc();
    print "There are only ", $#batch+1," processes, not $proc_n[$#proc_n].\n" unless $proc_n[$#proc_n] <= $#batch+1;
  }
  else {
    @proc_n= 1 .. $#batch+1;
  }

  while (-e "prt_".$Nsession and ! defined $insession) {
    $Nsession++
  }
  $Nsession = $insession if defined $insession;

# Run numerical CompHEP generator
  for ($i = 0; $i <= $#proc_n; $i++) {
    last if $proc_n[$i] > $#batch + 1;
    print "The current session is number $Nsession\n";
    @blocks = split(/\n#/,$batch[$proc_n[$i]-1]);
    $blocks[2] =~s/\d+/$Nsession/g;
    print "$blocks[1] \n";
    foreach (@blocks) {
      $_="\n#".$_ unless $_ eq "\n" or $_ eq "";
    }
    open(SES,"+>$fileses") or die "Can't create session.dat in $opt_d ($!)";
    print SES @blocks;
    close SES;

# Create subdirectories for each subprocess, setup there the session.dat
# and run run.sh in PBS or LSF batch system
    if (defined $pbs or defined $lsf) {
        my $pid;
        mkdir 'res_'.$Nsession,0777;
        chdir 'res_'.$Nsession;
        system("ln -s  ../n_comphep ./n_comphep");
        system("ln -s  ../n_comphep.exe ./n_comphep.exe") if -s "../n_comphep.exe";
        system("mv  ../session.dat .");

        open(FH,">run.sh");
        print FH $shell_scrpt;
        close(FH);
        chmod 0755, 'run.sh';
        $pid = fork();
        if ($pid == 0) {
          exec("$b_prefix ./run.sh");
          exit 0;
        }
        else {
          $count++;
        }
        chdir "../";
        $Nsession++;
      }
      else {
# usual batch calculation
        if (defined $run_p{"vegas"}) {
          $status=system ("./n_comphep", "-blind", "]]]]]$nginv]]]]}]]]}9}") ;
          open(PRT,"<prt_$Nsession") or die "Can't open prt_$Nsession in $opt_d ($!)";
          $/="\n";
          while (<PRT>) {
            print if /\s\#IT|\s\<\s\>/
          };
          print "\n";
          close PRT;
        }

        $status=system ("./n_comphep", "-blind", "]]]]]$nginv]]]]}]]]]]]]}]]]]}]]]}9}") if defined $run_p{"max"};
#        $status=system ("./n_comphep", "-blind", "]]]]]$nginv]]]]}]]]]]]]}]]]}9}")      if defined $run_p{"max"};
        $status=system ("./n_comphep", "-blind", "]]]]]$nginv]]]]}]]]]]]]}]]$noldf}9}") if defined $run_p{"evnt"};
        $status=system ("./n_comphep", "-blind", "]]]]]]]]]}]]]]]]}}9}")                if defined $run_p{"cleangrid"};
        $status=system ("./n_comphep", "-blind", "]]]]]]]]]}]]]]]}}9}")                 if defined $run_p{"cleanstat"};
#        $status=system ("./n_comphep", "-blind", "]]]]]]]]]}]]]]]}}]}}9}")              if defined $run_p{"clean"};
        $status=system ("./n_comphep", "-blind", "]]]]]]]]]}]]]]]}}]}}]}{9}")              if defined $run_p{"clean"};

        if (0 == $status) {
          open(SES,"<$fileses") or die "Can't read session.dat in $opt_d ($!)";
          local undef $/;
          $batch[$proc_n[$i]-1] = <SES>;
          $batch[$proc_n[$i]-1] .= "++++++++++++++\n";
          close SES;
          open(BATCH, "+>$filebat") or die "Can't open $filebat for read/write: $!\n";
          print BATCH @batch;
          close BATCH;

          $Nsession++;
        }
        else {
          print "Something wrong in calculations: $status \n" if $status != 0 ;
          exit(-1);
        }
      }
    }
# Wait until all of the subprocess to be calculated
  wait;

# clean cubic maxima
  if (defined $run_p{"clean"} or defined $run_p{"cleanstat"} or defined $run_p{"cleangrid"}) {
    replace_max ();
  }

# include the new session.dat parameters to batch.dat, move prt_ and events_
# files to main results dir and remove temporary res_ directories
  combine() if !defined $opt_nocombine;
  exit(0);
}

###################################################################################################
sub proc_nc {
  $proc =~ s/(\d+)-(\d+)/join(',',$1 .. $2)/eg;
  my @list = sort {$a <=> $b} split(/,/,$proc);
  my %temp= ();
  @proc_n = grep { !$temp{$_}++ } @list;
  return (@proc_n);
}

###################################################################################################
sub combine {
  my @list = <res_*>;
  foreach $resdir (@list) {
    $resdir=~/res\_(\d+)/g;
    my $resn=$1;
    my @keepfiles;
    $ses2bat="$resdir/$fileses";
    old_ses("$resdir/$fileses") if -e "$resdir/$fileses" ;
    if (-e "$resdir/prt_$resn") {
      $keepfiles[0]="$resdir/prt_$resn";
      move("$resdir/prt_$resn","prt_$resn");
    }

    if (-e "$resdir/events_$resn.txt") {
      $keepfiles[1]="$resdir/events_$resn.txt";
      move("$resdir/events_$resn.txt","events_$resn.txt");
    }
    eval {rmtree("$resdir")};
    if ($@) {
      print "Can not delete directory $resdir, reason:$@";
    }
    else {
      print "The $resdir directory is removed, @keepfiles files are kept\n";
    }
  }
}

###################################################################################################
sub list_batch {
  foreach (split(/,/,$show)) {
    $show_p{$_} = 1;
  }

  open(BATCH, "<$filebat") or die "Can't open $filebat for read: $!\n";
  local $/="++++++++++++++\n";

  unless (defined $show_p{"proc"}  or $show_p{"inistat"} or $show_p{"params"}  or
                  $show_p{"cuts"}  or $show_p{"regs"}    or $show_p{"qcd"}     or
                  $show_p{"vegas"} or $show_p{"events"}  or $show_p{"cs"}      ) {
    print "\nUnknown parameter in -show! \n";
    print "Use ./num_batch.pl -show proc|inistat|params|cuts|regs|qcd|vegas|events|cs\n\n";
    return;
  }

  my $cs_tot     = 0.0;
  my $cs_err_tot = 0.0;
  print "List of available subprocesses:\n";
  while (<BATCH>) {
    @blocks=split(/\n#/,$_) ;
    print "-----------------------------------------------------------\n" if defined $show_p{"inistat"} or $show_p{"params"} or
                                                                                     $show_p{"cuts"}    or $show_p{"regs"};
    print "$blocks[1] \n" if defined $show_p{"proc"};
    print "$blocks[1]:\n$blocks[3]  \n" if defined $show_p{"inistat"};
    print "$blocks[1]:\n$blocks[4]  \n" if defined $show_p{"params"};
    print "$blocks[1]:\n$blocks[7]  \n" if defined $show_p{"cuts"};
    print "$blocks[1]:\n$blocks[8]  \n" if defined $show_p{"regs"};
    print "$blocks[1]:  $blocks[9]  \n" if defined $show_p{"qcd"};
    print "$blocks[1]:  $blocks[10] \n" if defined $show_p{"vegas"};
    print "$blocks[1]:  $blocks[13] \n" if defined $show_p{"events"};
    if ($show_p{"cs"}) {
      if ($blocks[11] =~ /Vegas_integral\s+(\d\.\d+E[+-]\d+)\s+(\d\.\d+E[+-]\d+)\s+(\d\.\d+E[+-]\d+)\s+(\d+)\s+(\d+)\s+(\d+)/) {
        if (0.0 != $1) {
          $cs = $2/$1;
          $cs_err = sqrt($1)/abs($2);
        }
        else {
          $cs = 0.0;
          $cs_err = 0.0;
        }
        $cs_tot     = $cs_tot     + $cs;
        $cs_err_tot = $cs_err_tot + $cs_err * $cs_err;
        printf "%s: cross section [pb] = %1.4e   +\/- %1.2e \n", $blocks[1], $cs, $cs_err;
      }
    }
  }
  close(BATCH);
  printf "\n Total CS [pb] = %1.4e   +\/- %1.2e \n",$cs_tot, sqrt($cs_err_tot) if $show_p{"cs"};
  exit (0);
}

###################################################################################################
sub list_prt {
  print "Listed prt files: @ARGV \n\n" ;
  my $tot_cs   = 0;
  my $tot_err  = 0;
  my $tot_evnt = 0;
  my ($cs,$cs_err);

  print "\n   Cross section [pb]  Error %   nCall     chi**2     N of events\n\n";
  $i = 0;
  foreach (@ARGV) {
    open(PRT,"<$_") or die "Can't open $_ ($!)";
    $/="\n";
    $cs = 0.0;
    while ($line = <PRT>) {
      if ($line =~ /\s\<\s\>\s+(\d+\.\d+E[+-]\d+)\s+(\d+\.\d+E[+-]\d+)\s+\d+\s+.+/) {
        $cs = $1;
      }
    }
    close(PRT);
    $tot_cs  = $tot_cs + $cs;
    $i++;
  }

  $i = 0;
  foreach (@ARGV) {
    open(PRT,"<$_") or die "Can't open $_ ($!)";
    $lline = 0.0;
    while ($line = <PRT>) {
      if ($line =~ /\#Subprocess/) {
        $nline = $line;
      }
      if ($line =~ /\s\<\s\>\s+(\d+\.\d+E[+-]\d+)\s+(\d+\.\d+E[+-]\d+)\s+\d+\s+.+/) {
        $cs = $1;
        $cs_err =$1*$2/100;
        $revnt = 10000;
        if (defined $nevnt) {
          $revnt = sprintf("%.0f", $nevnt * $cs / $tot_cs);
        }
        $line =~ /(\s\<\s\>\s+\d+\.\d+E[+-]\d+\s+\d+\.\d+E[+-]\d+\s+\d+\s+.+)/;
        $lline = $1;
      }
    }
    close(PRT);
    print " $nline $lline $revnt \n";
    $tot_evnt = $tot_evnt + $revnt;
    $tot_err = $tot_err + $cs_err * $cs_err;
    $i++;
  }
  my $tot_err_p = sqrt($tot_err) * 100/$tot_cs;
  printf "\n Total CS [pb] = %1.4e   +\/- %1.2e ( %1.2e %% )\n",$tot_cs,sqrt($tot_err),$tot_err_p;
  print " Total Number of events = $tot_evnt\n\n";
  exit(0);
}

###################################################################################################
sub replace_nevnt {
  my $oldfilebat;
  my @cs;
  my @cs_err;

  $i=0;
  $tot_cs = 0;
  $tot_nevt = 0;
  $tot_cs_err = 0;
  $oldfilebat = $filebat.".BAK";
  move ($filebat, $oldfilebat);
  open(BATCH, "+<$oldfilebat") or die "Can't open $oldfilebat for read/write: $!\n";
  while ($line = <BATCH>) {
    if ($line =~ /\#Vegas_integral\s+(\d\.\d+E[+-]\d+)\s+(\d\.\d+E[+-]\d+)\s+(\d\.\d+E[+-]\d+)\s+(\d+)\s+(\d+)\s+(\d+)/) {
      $cs[$i] = $2/$1;
      $cs_err[$i] = sqrt($1)/abs($2);
      $tot_cs_err = $tot_cs_err + $cs_err[$i] * $cs_err[$i];
      $tot_cs = $tot_cs + $cs[$i];
      $i++;
    }
  }
  seek(BATCH,0,0);

  $i=0;
  my $tmp="";
  while ($line = <BATCH>) {
    if ($line =~ /\#Subprocess/) {
      print $line;
    }
    if ($line =~ /(\#Events\s+\d+\s+\d+\s+\d\.\d+\s+\d\.\d+\s+)(\d+)/) {
      $new_nevnt = sprintf("%.0f", $nevnt * $cs[$i] / $tot_cs);
      $line = $1.$new_nevnt."\n";
      printf " Cross section [pb] = %1.4e +\/- %1.2e (Nevnt = %i)\n", $cs[$i], $cs_err[$i], $new_nevnt;
      $tot_nevt = $tot_nevt + $new_nevnt;
      $i++;
    }
    $tmp .= $line;
  }
  close(BATCH);

  open(BATCH, ">$filebat") or die "Can't open $filebat for read/write: $!\n";
  print BATCH $tmp;
  close(BATCH);
  print "\n";
  printf " Total cross section [pb]  = %1.4e +\/- %1.2e (Ntotal = %i)\n", $tot_cs, sqrt($tot_cs_err), $tot_nevt;
  exit(0);
}

###################################################################################################
sub change_cs {
  local $/="\n#";

  foreach(@ARGV) {
    my $oldcs;
    my $newcs;
    my $file=$_;
    my $tmp = "";
    open(EVTFILE,"+<$file") or die "Can't open $file for read/write: $!\n";
    while (<EVTFILE>) {
      if ( /(.+section.+)\s(\d+\.\d+E[+-]\d+)\s+/ ) {
        $tmp .= "$1 ".sprintf("%E",$2*$kfactor)."\n#";
        $oldcs = $2;
        $newcs = $2*$kfactor;
      }
      else {
        $tmp .=$_ ;
      }
    }
    seek(EVTFILE,0,0);
    print EVTFILE $tmp;
    truncate (BATCH,tell(EVTFILE));
    close EVTFILE;
    print "file: $file, old cs: $oldcs, new cs: ".sprintf("%E",$newcs)."\n";
  }
  exit(0);
}

###################################################################################################
sub replace_calls {
  my $oldfilebat = $filebat.".BAK";
  my $tmp = "";
  move ($filebat, $oldfilebat);

  open(BATCH, "+<$oldfilebat") or die "Can't open $oldfilebat for read/write: $!\n";
  while ($line = <BATCH>) {
    if ($line =~ /(\#Vegas_calls\s+)(\d+)(x\d+)/) {
      $line = $1.$ncall.$3."\n";
    }
    $tmp .= $line;
  }
  close(BATCH);

  open(BATCH, ">$filebat") or die "Can't open $filebat for read/write: $!\n";
  print BATCH $tmp;
  close(BATCH);

  print "Number of calls replacement is finished\n";
  exit(0);
}

###################################################################################################
sub replace_max {
  my $oldfilebat = $filebat.".BAK";
  my $tmp = "";
  move ($filebat, $oldfilebat);

  open(BATCH, "+<$oldfilebat") or die "Can't open $oldfilebat for read/write: $!\n";
  while ($line = <BATCH>) {
    $line =~ s/Max:/!Max/;
    $tmp .= $line;
  }
  close(BATCH);

  open(BATCH, ">$filebat") or die "Can't open $filebat for read/write: $!\n";
  print BATCH $tmp;
  close(BATCH);
}

###################################################################################################
sub help
{
  print
  "Usage: \n
$0 [-d dir] [-run [vegas,max,evnt,cleanstat,cleangrid,clean]] [-proc N1,N2-N3,N4] [-nses N] [-old] [-ginv]
$0 [-d dir] [--add [file]]
$0 [-d dir] [-nevnt Nevents]
$0 [-d dir] [-call Ncalls]
$0 [-d dir] [-show [proc,inistat,params,cuts,regs,qcd,vegas,events,cs]]
$0 [-lcs [prt file names]]
$0 [-kfactor [factor] -files [event file names]]
$0 [-h] [--help]

/*****************************************************************/
/***  Launch numerical CompHEP in batch (single machine)       ***/
-run [vegas,max,evnt] - run vegas / maxima search / event generation,
                        run all steps: -run with no options;
-run [cleanstat,cleangrid,clean] - clean statistic / grid / clean both;
-proc n1,n2-n3,n4...  - run calculation for these processes only;
-nses n               - n is a number of the first session, it is
                        calculated automatically by default;
-ginv                 - gauge invariance ON (See CompHEP manual);
-old                  - generate events in the old CompHEP format
                        (compatible with cpyth-1.2.*);
-d new_dir            - use the directory new_dir instead of results
                        for this batch calculations;

/*****************************************************************/
/***  Batch system regime (computer farms)                     ***/
-pbs [pbs prefix] (e.g. qsub)  - run calculations in parallel with PBS batch system;
-lsf [lsf prefix] (e.g. bsub -I)  - run calculations in parallel with LSF batch system;
-nocombine            - do not combine automatically the results of
                       PBS (LSF) calculations from the temporary subdirectories
                       it can be done with the -combine option later;
-combine              - combine the results of previouse calculations from the
                       temporary PBS directories (you need it only if you used
                       -nocombine option before);

/*****************************************************************/
/***  Statistics and file manipulations                        ***/
-show ...             - print different parts of batch file
   [proc]             - subprocess list
   [inistat]          - initial state: beams, sqrt(S), PDF (of each subprocess)
   [params]           - print parameter list (for each subprocess)
   [cuts]             - print cuts applied list (for each subprocess)
   [regs]             - print regularization list (for each subprocess)
   [qcd]              - print qcd information (for each subprocess)
   [vegas]            - print vegas information (for each subprocess)
   [events]           - print events information (for each subprocess)
   [cs]               - print cross section of each subprocess and the full one;

-lcs  LIST            - report all cross sections in the results from prt_* files,
                        LIST is the list of prt files (e.g. prt_* or prt_1 prt_2 ...);
--add [file]          - add parameters from exist session.dat
                        file (or [file])  to batch.dat file in [dir]
-kfactor {factor}     - change cross sections in event files, the event file
                        names are set by the command -files
-files {file_names}   - set event file names to change cross sections in the
                        files (by an option -files)
-nevnt Nevents        - set the full number of events. The script sets the number
                        of event for each subprocess according to its contribution
                        to the full cross section;
-call Ncalls          - set a number of calls in vegas sesssions;

/*****************************************************************/
/***  Help options                                             ***/
-h                    - print this message
--help                - print the long help message \n";

  if (defined $longhelp) {
    print
"

/********************************************************************************/
1. Introduction.

  Numerical batch mode is a useful tool to calculate cross sections and generate
  events in tasks with the large number of subprocesses or where the large computer
  resources are required. It helps to perform the large scale calculations, even
  the calculations on MC farms (with the PBS and LSF batch systems).

  At first, a user should prepare a numerical CompHEP program - event generator -
  in graphical mode (see details in CompHEP manual). This script uses special
  'blind' keys to launch the program in the batch regime. The numerical program
  can also be prepared by the symb_batch.pl script.

/********************************************************************************/
2. Configuration of calculation task.

  At first, the generator should be configurated. All paramaters for the numerical
  sessions are stored in the file batch.dat. It is formed from session.dat. So
  the user should prepare session.dat with the generator GUI interface.

  cd results
  ./n_comphep

  The users sets all required parameters (PDF, QCD scale, kinematical cuts,
  regularizations, etc.) for the first process, check the vegas menu and close
  the program. The session.dat will be created.

  After that, the user runs the batch script with no options to create the configuration
  file (results/batch.dat) with the same parameters for all subprocesses
  as (s)he sets for the first one. The script should be run from the CompHEP
  working directory (CWDIR):

  $0

  By default, the directory 'results' will be used by this script to find and
  run the generator n_comphep.exe. The user can change the default name by
  the option -d {new_dir}. Use the option for all manipulation where you need
  a reference to the n_comphep.exe, e.g.:

  $0 -d new_dir

  If you want to change parameters of a particular subprocess you can edit the
  results/batch.dat file manually or use GUI: choose the required subprocess in
  GUI,   change the parameters, check the vegas menu and return to the main GUI
  menu   (this operation saves the parameters to session.dat). After that, the
  script can insert the new parameters to the results/batch.dat file (add session.dat
  to batch.dat) if you launch it with the command:

  $0 --add

/********************************************************************************/
3. How to start the calculations.

  If the configuration process of the program has been finished you are ready
  to start calculations. It can be done with the command -run:

  $0 -run

  with this command n_comphep.exe will calculate cross sections, find maxima
  and generate events for all of the subprocesses.

  The full process can be divided to separate steps:
  $0 -run vegas   : calculation of cross sections
  $0 -run max     : search for maxima
  $0 -run evnt    : event generation, can be used fter vegas
                    and max calculations only!

  There are several additional options, useful in practical calculations:
  $0 -run cleanstat   : clean the vegas statistic
  $0 -run cleangrid   : clean the vegas grid
  $0 -run clean       : clean the vegas grid and statistic

  The option -proc allows a specific set of subprocesses be calculated.
  For instance,

  $0 -run -proc 1,3-5,17,2

  means calculations for 1st, 3rd, 4th, 5th, 17th, 8th subprocesses,

  CompHEP stores all session details in protocal files, prt_XYZ, where XYZ is
  equal to the session number. By default, the number of a new session will be
  XYZ+1, where XYZ is the last sesstion number. The user can change the behaviour
  with the option -nses. E.g.

  $0 -d new_dir -run vegas -proc 2-10,12 -nses 20

  means calculations for the subprocesses 2-10,12 and the first session (for the
  2nd subprocess) will have the number 20. n_comphep.exe located in the directory
  new_dir will do thew calculations.

  WARNING! if prt_20 exists already, n_comphep.exe will append the details of the
  2th subprocess to the file, even the file corresponds to another subprocess.

/********************************************************************************/
4. Parallel calculations. Calculations with LSF or PBS systems.

  All of the commands described above provide the consecutive method of calculations
  of subprocesses. But the user can organize parallel calculations of the subprocesses,
  directly or running jobs in BATCH systems (LSF or PBS). There are two options
  -lsf and -pbs with almost the same functionality, but used in different (LSF or
  PBS) systems (different default prefixes and options).

  $0 -run vegas -pbs

  This command will create temporary subdirectories for each subprocess and run
  the PBS batch job for each of subprocess with PBS command:
  qsub -I run.sh

  or for LSF system
  $0 -run vegas -lsf
  will submit
  bsub -I run.sh

  After the jobs completion the script will remove the temporary subdirectories
  automatically and save the results in the usual manner.

  If your PBS or LSF system does not provide you interactive option ( -I ) you
  should add the -nocombine option.

  $0 -run vegas -lsf  -nocombine

  This command will submit the LSF jobs and exit immediately. When all of the
  submitted jobs will be finished the user can combine results from the
  temporary subdirectories by an additional command:

  $0 -combine

  If the user wants to change the default method to submit the jobs it is possible
  to run something like:

  $0 -run vegas -lsf 'bsub -I -q large -N -B -o log.out'

  Interactive parallel calculations can be launched with the empty prefix of the
  command:

  $0 -run vegas -lsf ' '

  In the case  will start calculations of the subprocesses in parallel and combine
  the results at the end.

  WARNING! The calculations with batch systems presume a direct access to
  n_comphep.exe and the CompHEP installation area (to PDF tables). So, if your
  computer farm nodes uses separate file systems, you have to edit the scripts
  run.sh and add a code which will copy all necessary files (the subdirectory
  and the PDF tables from the CompHEP area) to the farm nodes. Certainly, the
  code should copy all results to the corresponding subdirectories.


/********************************************************************************/
5. Presentation of results.

  There are two special options to summarize information in batch.dat or
  in protocol files.

  The option -lcs prints the cross sections and statistical errors from the
  protocol files. Examples of usage of the command:

  $0 -lcs prt_1 prt_2 prt_5
  $0 -lcs results/prt_*

  The command -show prints separate parts of batch.dat. For example,
  -show proc    : prints the full subprocess list,
  -show inistat : prints initial states: beams, sqrt(S), PDF
  -show params  : prints the list of physical parameters
  -show cuts    : prints the cuts applied list
  -show regs    : prints the regularization list
  -show qcd     : prints qcd information
  -show vegas   : prints vegas information
  -show events  : prints events information
  -show cs      : prints the the total one and cross sections of each subprocess

  Examples:

  $0 -show inistat
  $0 -d new_dir -show cs

/********************************************************************************/
6. Other manipulations in batch mode.

  By default, CompHEP sets the numbers of events for the event generation equal each
  other. Since subrpocesses have different cross sections, not all of the events will
  be used after the generation. The command -nevnt sets the total number of events
  for all subprocesses according to their contributions to the total cross section.
  For example,

  $0 -nevnt 100000

  means the full number of events generated by n_comphep.exe in all event files will
  be 100000. Since the further mixing of the event files is a statistical process,
  the real number of events in the final file will be between 100000 - sqrt(100000)
  and 100000.

  The command -call changes the number of calls in vegas sesssions. Usage:

  $0 -call 100000

  The commands -kfactor and -files are useful if a user wants to change cross
  sections of subprocesses in the event files prepared, so batch.dat is not changed.
  Sometimes the option is needed. Usage:

  $0 -kfactor 2.0 -files results/events_*

  It means all cross section in the files (results/events_*) will be doubled.

  \n";

  }
}
