#!/usr/local/bin/perl
# Author Tomasz Haupt  (haupt@npac.syr.edu) 1997
#===========================================================================

sub write_variables {
    local $fname=">Variables.h";
    open(VH,$fname) ||  die "cannot open $fname $!\n";
    print VH "#define GFlist List<GridFunction(1)<DOUBLE>*>\n";
    print VH "class V: public GFlist { \n";
    print VH "public: \n";

    local $astr="      V(";
    local $bstr="      ";

    for ($i=0; $i<$nvars; $i++) {
    print VH "      $type[$i] *$vars[$i]; \n";
    $astr=$astr.$type[$i]." *".$vars[$i]."_i, ";
    $bstr=$bstr.$vars[$i]."(".$vars[$i]."_i), ";
    }
    print VH "      DOUBLE *params; \n\n";
    $astr=$astr."DOUBLE *params_i)";
    $bstr=$bstr."params(params_i)";
    
# format list
    local $l=length($astr);
    local $comma=0;

    if($l>51) {
    local $newlist="";
    local @aw=split(//,$astr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $astr=$newlist;
  } 

# format list
    local $l=length($bstr);
    local $comma=0;

    if($l>51) {
    local $newlist="";
    local @aw=split(//,$bstr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $bstr=$newlist;
  } 

  print VH $astr;
  print VH "\n  :  \n";
  print VH $bstr;
  print VH "\n   {} \n  }; \n"; 
  print VH "\n#undef GFlist \n";
    close VH;
}

sub write_gfunc {
    local $fname=">GFunctions.h";
    open(VH,$fname) ||  die "cannot open $fname $!\n";

    for ($i=0; $i<$nvars; $i++) {

        if(($type[$i] eq "SArray") || ($type[$i] eq "TArray")) {
	    print VH "      $type[$i] *$vars[$i] = new $type[$i](";
            print VH "(*$vars[0]).spacetime[0]);\n";
        }
        else {
          print VH "      $type[$i] *$vars[$i] = new $type[$i](GH,s_sten";
            if($tste[$i]==0) {
	      print VH ");\n";
	    }
            elsif($tste[$i]==1) {
	      print VH ",1);\n";
	    }
            else {
              die "unsupported time stensil size $tste[$i]";
            }
        } 
    }
    print VH "\n";
    local $astr="V VA(";
    for($i=0; $i<$nvars; $i++) {
      $astr=$astr.$vars[$i].",";
    }
    $astr=$astr."params); \n";

# format list
    local $l=length($astr);
    local $comma=0;

    if($l>61) {
    local $newlist="";
    local @aw=split(//,$astr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $astr=$newlist;
  } 

    print VH $astr;
    close VH;
  
}

sub write_initdata0 {

    local $fname=">InitData0.C";
    local $fname2=">init.h";    

    open(VH,$fname) ||  die "cannot open $fname $!\n";
    open(VI,$fname2) ||  die "cannot open $fname2 $!\n";
    
    print VH '#include "DAGH.h"',"\n"; 
    print VH '#include "Consts.h"',"\n"; 
    print VH '#include "ADMvar.h"',"\n"; 
    print VH '#include "SArray.h"',"\n"; 
    print VH '#include "TArray.h"',"\n"; 
    print VH '#include "BHmask.h"',"\n"; 
    print VH '#include "Variables.h"',"\n";
    print VH '#include "init.h"',"\n"; 
    print VH '#include "input_params.h"',"\n"; 
    print VH "\n";
    print VH "void init(int, int, double *,\n";

    for ($i=0; $i<$nvars; $i++) {
      print VH "      $type[$i] *, \n";
    }

    print VH "      int, int, double, int); \n\n";
    print VH "void InitData0(V &VA, double Time, double Delta_t, int tc,\n";
    print VH "      int Level, int IDENT, int myrank) {\n";

    for ($i=0; $i<$nvars; $i++) {
      print VH "      $type[$i] *$vars[$i]=VA.$vars[$i];\n";
    } 
    print VH "      DOUBLE *params=VA.params;\n";
    
    print VH " \n";
    print VH "      int iTime=0;\n";
    print VH "      int idt=1;\n";
    print VH "      int init=1;\n";
    print VH " \n";

    local $astr="initialize(iTime, Level, params, ";
    local $bstr="void initialize(INTEGER t, INTEGER Level, DOUBLE *params, ";

    for ($i=0; $i<$nvars; $i++) {
       $astr=$astr.$vars[$i].", ";
       $bstr=$bstr.$type[$i]." *".$vars[$i].", ";
    }
    $astr=$astr."init, idt, Time, myrank);";
    $bstr=$bstr."INTEGER init, INTEGER idt, DOUBLE Time, INTEGER myrank)";

# format list
    local $l=length($astr);
    local $comma=0;

    if($l>51) {
    local $newlist="";
    local @aw=split(//,$astr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $astr=$newlist;
  } 

# format list
    local $l=length($bstr);
    local $comma=0;

    if($l>51) {
    local $newlist="";
    local @aw=split(//,$bstr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $bstr=$newlist;
  } 

    print VH $astr,"\n\n";
    print VH 'if(myrank==0) cout << "initialization completed" << endl;',"\n";
    print VH "}\n";
    print VI $bstr,";\n";
     
    close VH;
    close VI;
}


sub write_init {
    local $fname=">init.C";
    open(VH,$fname) ||  die "cannot open $fname $!\n";
    
# ---symbol table first
 
    local $tmp = "";
    for($i=0; $i<$nsym; $i++) {
        $tmp = $st_type[$i];
        if ($tmp =~ /ADM/) {
	    $tmp =~ /ADM(.+)/;
            $tmp = $1;x
	}
  	print VH "// $st_vars[$i] $tmp $st_type_m[$i] $st_type_p[$i]\n";
    }
    print VH "// end of the list of the variables \n\n\n";


    print VH '#include "DAGH.h"',"\n"; 
    print VH '#include "Consts.h"',"\n"; 
    print VH '#include "ADMvar.h"',"\n"; 
    print VH '#include "SArray.h"',"\n"; 
    print VH '#include "TArray.h"',"\n"; 
    print VH '#include "BHmask.h"',"\n"; 
    print VH '#include "Variables.h"',"\n";
    print VH '#include "initfortran.h"',"\n"; 
    print VH '#include "input_params.h"',"\n"; 
    print VH '#include "tstep.h"',"\n";
    print VH "\n";

    local $astr="void initialize(int t, int Level, double *params, ";

    for ($i=0; $i<$nvars; $i++) {
       $astr=$astr.$type[$i]." *".$vars[$i].", ";
    }
    $astr=$astr."int init, int idt, double Time, int myrank)";

# format list
    local $l=length($astr);
    local $comma=0;

    if($l>51) {
    local $newlist="";
    local @aw=split(//,$astr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $astr=$newlist;
  } 

    print VH $astr,"\n\n";
    print VH "{\n";
    print VH "int itc;\n";
    print VH "int cg;\n";
    print VH "GridFunction(DIM)<DOUBLE> &st = *(*$vars[0]).spacetime[0];\n";
    print VH "int *ntmp = (*(*theMask).nl).data();\n";
    print VH "int *ni   = (*(*shift_p).n).data();\n";
    print VH "int *nio  = (*(*shift_po).n).data();\n";
    print VH "int *npi  = (*(*shift_t).n).data();\n";
    print VH "int nl;\n";
    print VH "int num_int_points;\n";
    print VH "int num_int_pointso;\n";
    print VH "int np;\n";

    print VH "\n//DAGH: insert body here\n";
    print VH "\n}\n";
     
    close VH;
}

sub write_evolve0 {
    local $fname=">Evolve0.C";
    local $fname2=">tstep.h";
    local $fname3=">tstepcall";

    open(VH,$fname) ||  die "cannot open $fname $!\n";
    open(VI,$fname2) ||  die "cannot open $fname2 $!\n";
    open(VT,$fname3) || die "cannot open $fname3 $!\n";
    
    print VH '#include "DAGH.h"',"\n"; 
    print VH '#include "Consts.h"',"\n"; 
    print VH '#include "ADMvar.h"',"\n"; 
    print VH '#include "SArray.h"',"\n"; 
    print VH '#include "TArray.h"',"\n"; 
    print VH '#include "BHmask.h"',"\n"; 
    print VH '#include "Variables.h"',"\n";
    print VH '#include "tstep.h"',"\n"; 
    print VH '#include "input_params.h"',"\n"; 
    print VH "\n";
    print VH "void tstep(int, int, double *,\n";

    for ($i=0; $i<$nvars; $i++) {
      print VH "      $type[$i] *, \n";
    }
    print VH "      int, int, double, int); \n\n";
    print VH "void Evolve0(V &VA, double Time, double Delta_t, int t,\n";
    print VH "      int Level, int IDENT, int myrank) {\n";

    for ($i=0; $i<$nvars; $i++) {
      print VH "      $type[$i] *$vars[$i]=VA.$vars[$i];\n";
    } 

    print VH "double *params=VA.params;\n";
    
    print VH " \n";
    print VH "      int init=0;\n";
    print VH "      int idt=1;\n";
    print VH " \n";

    local $astr="tstep(t, Level, params, ";
    local $bstr="void tstep(INTEGER t, INTEGER Level, DOUBLE *params, "; 

    for ($i=0; $i<$nvars; $i++) {
       $astr=$astr.$vars[$i].", ";
       $bstr=$bstr.$type[$i]." *".$vars[$i].", ";
    }
    $astr=$astr."init, idt, Time, myrank);";
    $bstr=$bstr."INTEGER init, INTEGER idt, DOUBLE Time, INTEGER myrank)";

# format list
    local $l=length($astr);
    local $comma=0;

    if($l>51) {
    local $newlist="";
    local @aw=split(//,$astr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $astr=$newlist;
  } 

# format list
    $l=length($bstr);
    $comma=0;

    if($l>51) {
     $newlist="";
     @aw=split(//,$bstr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $bstr=$newlist;
  } 

    print VH $astr,"\n\n";
    print VH "}\n";
    print VI $bstr,";\n";

    print VT $astr,"\n";

    close VH;
    close VI;
    close VT;
}

sub write_tstep {
    local $fname=">tstep.C";
    open(VH,$fname) ||  die "cannot open $fname $!\n";

# ---symbol table first

    local $tmp = "";
    for($i=0; $i<$nsym; $i++) {
        $tmp = $st_type[$i];
        if ($tmp =~ /ADM/) {
	    $tmp =~ /ADM(.+)/;
            $tmp = $1;
	}
  	print VH "// $st_vars[$i] $tmp $st_type_m[$i] $st_type_p[$i]\n";
    }
    print VH "// end of the list of the variables \n\n\n";

    
    print VH '#include "DAGH.h"',"\n"; 
    print VH '#include "Consts.h"',"\n"; 
    print VH '#include "ADMvar.h"',"\n"; 
    print VH '#include "SArray.h"',"\n"; 
    print VH '#include "TArray.h"',"\n"; 
    print VH '#include "BHmask.h"',"\n"; 
    print VH '#include "Variables.h"',"\n";
    print VH '#include "fortran.h"',"\n"; 
    print VH '#include "input_params.h"',"\n"; 
    print VH "\n";

    local $astr="void  tstep(int t, int Level, double *params, ";

    for ($i=0; $i<$nvars; $i++) {
       $astr=$astr.$type[$i]." *".$vars[$i].", ";
    }
    $astr=$astr."int init, int idt, double Time, int myrank)";

# format list
    local $l=length($astr);
    local $comma=0;

    if($l>51) {
    local $newlist="";
    local @aw=split(//,$astr);
    for($i=0;$i<$l;$i++) {
      $newlist=$newlist.$aw[$i];
        if($i>0 && $i%60 == 0) {
           $comma=1;
        }
    if(($comma==1) && ($aw[$i] eq ",")) {
       $newlist=$newlist."\n     ";
       $comma=0;
    }
   }
   $astr=$newlist;
  } 

    print VH $astr,"\n\n";
    print VH "{\n";
    print VH "INTEGER itc;\n";
    print VH "DOUBLE endtime;\n";
    print VH "INTEGER cg;\n";
    print VH "GridFunction(DIM)<DOUBLE> &st = *(*$vars[0]).spacetime[0];\n";
    print VH "int *ntmp = (*(*theMask).nl).data();\n";
    print VH "int *ni   = (*(*shift_p).n).data();\n";
    print VH "int *nio  = (*(*shift_po).n).data();\n";
    print VH "int *npi  = (*(*shift_t).n).data();\n";
    print VH "int nl;\n";
    print VH "int num_int_points;\n";
    print VH "int num_int_pointso;\n";
    print VH "int np;\n";
    print VH "\n//DAGH: insert body here\n";
    print VH "\n}\n";
     
    close VH;
}

sub write_params {

    local $filename=">input_params.h";
    open(INFH,"input_params.f90") || die "cannot open input_params.f90 $! \n";
    open(OUTFH,$filename) || die "cannot open $filename $! \n";

    local @w=();
    local $value;
    while($line=<INFH>) {
        if($line =~ /integer, parameter/) {
	    $line =~ /integer, parameter :: (.+)/;
            $line = $1;
            @w=split(",",$line);   
            foreach $i (@w) {
		$i =~ /([0-9A-Z_]+) = ([0-9]+)/;
                $value = $2-1;
		print OUTFH "#define $1 $value \n";
            }
        }      
    }
    close INFH;
    close OUTFH;
}
# ------------- main routine ----------------------------------------------


if($#ARGV > -1) {
  $infile=$ARGV[0];
  }
else {
  $infile="parameters.f90";
  }

print "reading file $infile \n";

open(VARS, $infile) || die "cannot open file $infile $!\n";

$nvars=0;
LINE: while($line=<VARS>) {
    last LINE if $line =~ /end of ADM/;
    if($line =~ /!DAGH\$/) {
	@w = split(" ",$line);
        if($#w < 2) {die "error 01 wrong DAGH directive";};
	@type[$nvars]=$w[1];
	@vars[$nvars]=$w[2];
        @tste[$nvars]=$w[3];
        $nvars++;
    }
}
    
      close VARS;

# for symbol table
open(VARS, $infile) || die "cannot open file $infile\n";

$nsym=0;
  while($line=<VARS>) {
    if($line =~ /!DAGH\$/) {
	@w = split(" ",$line);
        if($#w < 1) {die "error 01 wrong DAGH directive";};
	@st_type[$nsym]=$w[1];
	@st_vars[$nsym]=$w[2];
        @st_type_m[$nsym]=$w[4];
        @st_type_p[$nsym]=$w[5];
        $nsym++;
    }
}
    
      close VARS;
  
&write_variables();

&write_gfunc();

&write_initdata0();

&write_init();

&write_evolve0();

&write_tstep();

&write_params();




