#!/usr/local/bin/perl
#<
#paralize
#
#Usage:
#paralize  <in.H >out.H
#
#Input Parameters:
#
#
#Output Parameters:
#
#Description
#
#
#
#-------------------------------------------------
#
#Author: Robert Clapp, ESMB 463, 7230253
#
#Date Created:Sat Jun 28 20:55:31 PDT 1997
#
#Purpose: 
#
#>

&parse_args;       #Grab and parse arguments

#now we need to loop over sections sending outjobs
&start_jobs;       #Start parallel jobs
$jobs=$jobs*$sections; 
print STDERR "check $jobs \n";
$int=0; $e=$jobs; $b=0; $e2=$e;
&cat_jobs;


##############################################################################
##############################################################################
############################ parse_args  #####################################
##############################################################################
##############################################################################

sub parse_args{

$selfdoc="paralize.x parfile  
prog - string             \"program\" to run[required]
ovar - string             variable that will be used for steps[required]
oval - real/integer       initial value[required]
dval - real/integer       [1.] sampling along split axis [required]
otype - string            [real] type of variable for ovar
nvar - string             variable corresponding to number of steps[required]
nval - integer            number of steps[required]
axis - integer            axis to catenate along[required]
jobs - integer            [1] number of jobs to distribute work along
in   -  file              \"input\" file
out  -  file              \"output\" file[required]
outtag - file             \"tag \" of output need to catenate,defaults to stdout
par     - string          \"parfile\"
window_prog - string      what program to use window input, if not
                          specified no windowing
ovar_win - string         variable that will be used for windowing 
                          steps[required with window_prog]
oval_win - real/integer   initial windowing value[required with window_prog]
dval_win - real/integer   [1.] sampling along windowing axis [required with 
                          window_prog]
otype_win - string        [real] type of variable for ovar_win
nvar_win - string         variable corresponding to number of steps for
                          windowing [required with window_prog]
min_win_axis -real/integer minimum value oval_win can have [useful for sending
                          sections [none]
max_win_axis -real/integer maximum value oval_win can have [useful for sending
                          sections [none]
window_par_file -char     window parameter file 
sections     -integer     [1] number of sections to break the job into
                           sections*jobs=total number of jobs
verb         -integer     [0] print out commands
run          -integer     [1] run commands
\n";


if($#ARGV <0){
  print STDERR $selfdoc,"\n";
  exit; 
}
	

$arguments="";
for($i1=1;$i1<= $#ARGV; $i1++){ $list.=$ARGV[$i1]."\n";}

if (!open(PARS, $ARGV[0])){ 
	print STDERR $ARGV[0],"\n";
	print STDERR "Can not open par file \n",$selfdoc," \n";
	exit;
}

while(<PARS>){ $list.=$_."\n";}
close(PARS);

@array=split("\n",$list);

$program=0; $ovar=0; $oval=0; $nvar=0;  $nval=0; $axis=0; $jobs=1;
$infile=0; $outfile=0; $type=1; $parfile=0;$outtag=">";$dval=1.;
$window_prog=0; $ovar_win=0; $oval_win=0; $dval_win=0; $nvar_win=0;
$min_win_axis=0; $max_win_axis=0;$type_win=1;$sections=1;
$verb=0; $run=1; $nval_win=0;


for($i1=0; $i1 < @array; $i1++){
	if($array[$i1] =~/^([\s\S]*)#/){ $line=$1;} else{$line=$array[$i1];}
	if($line=~ /^\s*prog\s*=\s*([\s\S]+)/){ $program=1; $program_v=$1;}
	if($line=~ /^\s*window_prog\s*=\s*([\s\S]+)/){ $window_prog=1; $window_prog_v=$1; }
	elsif($line=~ /^\s*ovar\s*=\s*([\S]+)/){ $ovar=1; $ovar_v=$1;}
	elsif($line=~ /^\s*oval\s*=\s*([\S]+)/){ $oval=1; $oval_v=$1;}
	elsif($line=~ /^\s*nvar\s*=\s*([\S]+)/){ $nvar=1; $nvar_v=$1;}
	elsif($line=~ /^\s*nval\s*=\s*([\S]+)/){ $nval=1; $nval_v=$1;}
	elsif($line=~ /^\s*axis\s*=\s*([\S]+)/){ $axis=1; $axis_v=$1;}
	elsif($line=~ /^\s*dval\s*=\s*([\S]+)/){ $dval=$1;}
	elsif($line=~ /^\s*jobs\s*=\s*([\S]+)/){ $jobs=$1;}
	elsif($line=~ /^\s*run\s*=\s*([\S]+)/){ $run=$1;}
	elsif($line=~ /^\s*in\s*=\s*([\s\S]+)/){ $infile=1; $infile_v=$1;}
	elsif($line=~ /^\s*out\s*=\s*([\s\S]+)/){ $outfile=1; $outfile_v=$1;}
	elsif($line=~ /^\s*par\s*=\s*([\s\S]+)/){ $parfile=1; $parfile_v=$1;}
	elsif($line=~ /^\s*outtag\s*=\s*([\s\S]+)/){ $outtag=">/dev/null ".$1."=";}
	elsif($line=~ /^\s*min_win_axis\s*=\s*([\S]+)/){ 
		$min_win_axis=1; $min_win_axis_v=$1;}
	elsif($line=~ /^\s*max_win_axis\s*=\s*([\S]+)/){ 
		$max_win_axis=1; $max_win_axis_v=$1;}
	elsif($line=~ /^\s*ovar_win\s*=\s*([\S]+)/){$ovar_win=1; $ovar_win_v=$1;}
	elsif($line=~ /^\s*oval_win\s*=\s*([\S]+)/){$oval_win=1; $oval_win_v=$1;}
	elsif($line=~ /^\s*dval_win\s*=\s*([\S]+)/){$dval_win=1; $dval_win_v=$1;}
	elsif($line=~ /^\s*nval_win\s*=\s*([\S]+)/){$nval_win=1; $nval_win_v=$1;}
	elsif($line=~ /^\s*nvar_win\s*=\s*([\S]+)/){$nvar_win=1; $nvar_win_v=$1;}
	elsif($line=~ /^\s*sections\s*=\s*([\S]+)/){$sections=$1; }
	elsif($line=~ /^\s*window_par_file\s*=\s*([\S]+)/){$window_par_file=1; $window_par_file_v=$1;}
	elsif($line=~ /^\s*verb\s*=\s*([\S]+)/){$verb=$1;}
	elsif($line=~ /^\s*otype\s*=\s*([\S]+)/){ 
		if($1 eq "real" ){} elsif($1 eq "integer"){ $type=0;}else{
			print STDERR "unacceptable type, must be real or integer\n";exit;
		}
	}
	elsif($line=~ /^\s*otype_win\s*=\s*([\S]+)/){ 
		if($1 eq "real" ){} elsif($1 eq "integer"){ $type_win=0;}else{
			print STDERR "unacceptable type, must be real or integer\n";exit;
		}
	}
	elsif($line=~ /^\s*\S+=([\S]+)/){ $extra.=" ".$line;}
}

if($program==0){ 
	print STDERR "need to specify prog \n", $selfdoc,"\n"; exit;
}
if($axis==0){ 
	print STDERR "need to specify axis \n ",$selfdoc,"\n"; exit;
}
if($nval==0){ 
	print STDERR "need to specify nval \n ",$selfdoc,"\n"; exit;
}
if($nvar==0){ 
	print STDERR "need to specify nvar \n ",$selfdoc,"\n"; exit;
}
if($oval==0){ 
	print STDERR "need to specify oval \n ",$selfdoc,"\n"; exit;
}
if($ovar==0){ 
	print STDERR "need to specify ovar \n ",$selfdoc,"\n"; exit;
}
if($outfile==0){ 
	print STDERR "need to specify out \n ",$selfdoc,"\n"; exit;
}
if($window_prog==1){
	if($ovar_win==0){
		print STDERR "need to specify ovar_win if you specify window_prog \n ",$selfdoc,"\n"; exit;
	}
	if($oval_win==0){
		print STDERR "need to specify oval_win if you specify window_prog \n ",$selfdoc,"\n"; exit;
	}
	if($dval_win==0){
		print STDERR "need to specify dval_win if you specify window_prog \n ",$selfdoc,"\n"; exit;
	}
	if($nval_win==0){
		print STDERR "need to specify nval_win if you specify window_prog \n ",$selfdoc,"\n"; exit;
	}
	if($nvar_win==0){
		print STDERR "need to specify nvar_win if you specify window_prog \n ",$selfdoc,"\n"; exit;
	}
}
}

##############################################################################
##############################################################################
############################ start_jobs  #####################################
##############################################################################
##############################################################################

sub start_jobs{


#construct non-variable portion of the command 
$main_core="$program_v  $extra ";
#change this

if($infile==1 && $window_prog ==0 ){ $main_core.="<".$infile_v." ";}
if($parfile==1){ $main_core.="par=".$parfile_v." ";}
if($window_prog==1){ 
	$window_core=" <$infile_v $window_prog_v ";;
	if($window_par_file==1){
		$window_core.="par=$window_par_file_v ";
	}
	if($type_win==0){ $ocur_win=int($oval_win_v);}
	else {$ocur_win=$oval_win_v;}
	$nleft_win=int($nval_win_v);
}
#print STDERR "JOBS=$jobs SECTIONS=$sections \n";

#figure out starting positions and number per job
if($type==0){ $ocur=int($oval_v);}
else {$ocur=$oval_v;}
$nleft=int($nval_v);
for($i1=0 ; $i1 < $jobs*$sections; $i1++){
	if($type==0){ $osend[$i1]=int($ocur);}
	else {$osend[$i1]=$ocur;}
	$nsend[$i1]=int($nleft/($jobs*$sections-$i1));
	$ocur+=$nsend[$i1]*$dval;
	$nleft-=$nsend[$i1];

	if($window_prog==1){
		if($type_win==0){ $osend_win[$i1]=int($ocur_win);}
		else {$osend_win[$i1]=$ocur_win;}
		$nsend_win[$i1]=int($nleft_win/($jobs*$sections-$i1));
		$ocur_win+=$nsend_win[$i1]*$dval_win;
		$nleft_win-=$nsend_win[$i1];
		if($min_win_axis ==1){
			if($osend_win[$i1] < $min_win_axis_v){$osend_win[$i1]=$min_win_axis_v;}
		}
		if($max_win_axis ==1){
			if($osend_win[$i1] + $nsend_win[$i1] > $max_win_axis_v){
				$nsend_win[$i1]=$max_win_axis_v-$osend_win[$i1];}
		}
	}
}

#now time to start jobs, not sure why I didn't put this above
#loop.

for($ia=0; $ia < $sections; $ia++){
	for($ib=0; $ib < $jobs; $ib++){
		$i1=$ia*$jobs+$ib;
		$file[$i1]="j".time.$i1.".H";
		$file_win[$i1]="a".time.$i1.".H";
		$command="";
		if($window_prog ==1){
			if($type_win==1){	 $i=int($osend_wind[$i1]);$command="$window_core $ovar_win_v=$i $nvar_win_v=$nsend_win[$i1] >  $file_win[i$1] ; < $file_win[$i1] ";
		}
		else{
			$i=int($nsend_win[$i1]);
			$command="$window_core $ovar_win_v=$osend_win[$i1] $nvar_win_v=$i >  $file_win[$i1] ; < $file_win[$i1] ";
		}
	}
	if($type==0){
		$command.=$main_core." ".$ovar_v."=".int($osend[$i1])." ".$nvar_v."=".int($nsend[$i1]).$outtag.$file[$i1];
	}
	else{
		$command.=$main_core." ".$ovar_v."=".$osend[$i1]." ".$nvar_v."=".int($nsend[$i1]).$outtag.$file[$i1];
	}
	if($window_prog==1){$command.="; Rm  $file_win[$i1]* | ";}
	else {
	$command.=" |";
	}
	if($verb==1){print STDERR "ABOUT TO ISSUE $command \n";}
	$handles[$i1]="J".$i1;
	if($run==1){open($handles[$i1],$command);}
}

#we need to wait for the jobs to finnish

	for($ib=0; $ib< $jobs; $ib++){
		$i1=$ia*$jobs+$ib;
		if($run==1){ close($handles[$i1]);}
		print STDERR "closed the ",$i1," job ",`time`,"\n";
	}
}

#exit;
	

}

##############################################################################
##############################################################################
############################  cat_jobs   #####################################
##############################################################################
##############################################################################

sub cat_jobs{


#this is limiting but right now I am going to assume that I 
#am doing a max of 15 jobs


$core="Cat axis=".int($axis_v);

print STDERR "i see $b $e \n" ;

$logic=0;
while($logic==0){
	if($e-$b < 9) { $max=$e;$logic=1;} else {$max=$b+8;}
	$list="";
	for($i=$b; $i<$max; $i++){ $list.=" $file[$i]"; }
	$command="$core $list > intermediate.$int.H";
	if($verb==1){print STDERR "ABOUT TO ISSUE $command \n";}
	if($run==1){system($command);}
	$command="Rm ".$list;
	if($verb==1){print STDERR "ABOUT TO ISSUE $command \n";}
	if($run==1){system($command);}
	$file[$e2] ="intermediate.$int.H"; $b=$max;$e2++; $int++;
}
	
	if($e2 -$b > 8){ $b=$e; $e=$e2; &cat_jobs;}

	else{
		$list="";
		for($i=$b; $i<$e2; $i++){ $list.=" $file[$i]"; }
		$command="$core $list > $outfile_v";
		if($verb==1){print STDERR "ABOUT TO ISSUE $command \n";}
		if($run==1){system($command);}
		$command="Rm  ".$list;
		if($verb==1){print STDERR "ABOUT TO ISSUE $command \n";}
		if($run==1){system($command);}
	}
}

	
