#!/usr/bin/perl
# $Id: resistance_calc_3.0.pl,v 1.33 2021/02/01 11:30:44 sqko Exp $
use AFM;
my $i_min_Rmin_calc = &get_cv('resistance_calc','minimum_relative_current_Rmin');
my $debug = 0;
my $backup_h2_conc = 0.09;
&setup();
my $line = <IVTABLE>;
exit unless ($line);
do {
    initvalues();

    # calculate values for each line of iv-data
    if ($line) {
        callcalc();

        printavgvalues();
        split_up_down();

        get_result_fields();
        make_sorted_power_and_r_sec_files();
        make_r_sec_files_vs_cell_voltage_and_current_for_interpolation();
        getstartvalues_current_gt_eps();
        get_min_max_values();
        interpolate_resistance_current_values();
        interpolate_voltage_current_values();
    }
    $line = <IVTABLE>;
} while ($line);

exit;

sub setup {
#    $currentresistance = 0.15;
    @resistance_current_values = ( "0.065", "0.25", "0.5" );
    @current_values = ( "0.3", "0.5", "0.8", "1.0" );
    if ( scalar(@ARGV) < 1 ) {
        print 'Use: resistance_calc.pl $rig   $testno  where $rig is the rig number' . "\n";
        print 'and $testno is the test number' . "\n";
        exit 1;
    }
    $ii = 0;
    for my $string (@ARGV) {
        $debug = 1 if ( $string =~ /--debug/ );
    }
    $rigno = $ARGV[0];
    if ( !&AFM::check_rig_nr($rigno) ) {
        print "Rig $rigno is not valid!\n";
        exit 1;
    }
    $testno = 0;
    if ( scalar(@ARGV) > 1 ) {
        $ttestno = $ARGV[1];
        $ttestno =~ /(\d+)/;
        $testno = $1;
    }
    $predominant_current = 1;
    if ( scalar(@ARGV) > 2 ) {
        $tpredominant_current = $ARGV[2];
        $tpredominant_current =~ /([\.\d\-]+)/;
        $predominant_current = $1;
    }
    $currentlabel = &AFM::get_usercv_test($rigno,$testno,'IV_control','current_label');
    $voltlabel = &AFM::get_usercv_test($rigno,$testno,'IV_control','voltage_label');
    $templabel = &AFM::get_usercv_test($rigno,$testno,'IV_control','temp_label');
    $presslabel = &AFM::get_usercv_test($rigno,$testno,'IV_control','pressure_label');
    $presslabel = 'pressure' unless ($presslabel);
    $currentlabel = 'current' unless ($currentlabel); ## Default value for backwards compatibility ###
    $voltlabel = 'cell_voltage' unless ($voltlabel);  ## Default value for backwards compatibility ###
    $templabel = 'T_center' unless ($templabel); ## Default value for backwards compatibility ###
    $currentepsilon = &AFM::get_usercv_test($rigno,$testno,'IV_control','epsilon');
    $currentepsilon = &AFM::get_usercv_test($rigno,$testno,'current','epsilon') unless ($currentepsilon);
    $currentepsilon    = 0.05 unless ($currentepsilon);
    $backup_h2_conc = &AFM::get_usercv_test($rigno,$testno,'main','backup_h2_conc');
    $backup_h2_conc = 0.09 unless ($backup_h2_conc);
    $area = &AFM::get_usercv_test($rigno,$testno,'main','cell_area');
    $area = &AFM::get_config_value_old($rigno,'area',$testno) unless ($area);
    $htmllocation =  $AFM::publicdir. 'rig' . $rigno . '/' . $rigno . 'test' . $testno;
    $ivtablefile = $htmllocation . "/iv/ivtable";
    if ( !( -e ($ivtablefile) ) ) {
        print "$ivtablefile  not found!!\n";
        exit 1;
    }
    $ivavgtablefile = $htmllocation . "/iv/ivtable-avg";
    $plotfile = $htmllocation . "/jdata";
    open( IVTABLE,'<', $ivtablefile ) || die ("Could not open $ivtablefile");
    open( IVAVGTABLE, '>', $ivavgtablefile ) || die ("Could not open $ivavgtablefile");
    $plotdir = $htmllocation . '/iv/plotdata';
    system("/bin/rm -rf  $plotdir") if (-d $plotdir);
    system("/bin/mkdir $plotdir");
    #### Get list of gasses ###
    @gaslst = split(/\s*\,\s*/,&AFM::get_usercv_test($rigno,$testno,'main','gas_names'));
    @gaslst = split(/\:/,&AFM::get_config_value_old($rigno,'gas_name',$testno)) unless (@gaslst);
    @gaslst = ('h2','o2','air','ch4','backup','sweep') unless (@gaslst);
    %cutoff = ();
    ### Get cutoff values for all gasses ###
    for my $g ('h2','o2','air','o2_cathode','n2_cathode','co','co2','ch4','n2','ar','he','nh3','backup')
    {
	my $c = &AFM::get_usercv_test( $rigno, $testno, 'gas_'.$g , 'cutoff_report' );
	$c = &AFM::get_config_value_old($rigno,$g.'_cutoff',$testno) unless (defined($c));
	$c = 0 unless (defined($c) && $c > 0);
	$cutoff{$g} = $c;
	print "Cutoff for $g: $c L/hour\n" if ($debug);
    }
}

sub initvalues {

    #    $line    = <IVTABLE>;
    $sumocv      = 0;
    $sumocvup    = 0;
    $sumocvdown  = 0;
    $iocv        = 0;
    $iocvup      = 0;
    $iocvdown    = 0;
    $sumtemp     = 0;
    $sumtempup   = 0;
    $sumtempdown = 0;

    ++$lineno;

    print "##### Processing line $lineno #####\n";
    $outdir = $htmllocation . "/iv/ivdatadir-" . $lineno;
    if ( !( -d $outdir ) ) { system("mkdir $outdir") }
    $outfile = $outdir . "/ivdata";
    open( OUTFILE, "> $outfile" );

    @Fld = split ( ' ', $line, 9999 );
    for ( $ii1 = 0 ; $ii1 < $#Fld ; $ii1 += 2 ) {

        $tabledata{ $Fld[$ii1] } = $Fld[ $ii1 + 1 ];
    }

    $cstr =
      "/bin/awk \'NR>="
      . $tabledata{'nstart'}
      . "&&NR<="
      . $tabledata{'nstop'} . "\' "
      . $plotfile;

    @ivdata = `$cstr`;

    #calculate avg values and ocv

    for ( $i = 0 ; $i < $#ivdata ; $i++ ) {

        @Fld = split ( ' ', $ivdata[$i], 9999 );
        for ( $ii = 2 ; $ii <= $#Fld ; $ii += 2 ) {
            $ivfield{ $Fld[$ii] } = $Fld[ $ii + 1 ];
            if ( $i == 0 ) { $ivfieldsum{ $Fld[$ii] } = 0 }
            $ivfieldsum{ $Fld[$ii] } += $Fld[ $ii + 1 ];

        }

        if ( abs($ivfield{$currentlabel}) < $currentepsilon ) {
            $iocv++;
            $sumocv  += $ivfield{$voltlabel};
            $sumtemp += $ivfield{$templabel};
            if ( $i < ( $tabledata{'ncmax'} - $tabledata{'nstart'} ) ) {
                $iocvup++;
                $sumocvup  += $ivfield{$voltlabel};
                $sumtempup += $ivfield{$templabel};
            }
            else {
                $iocvdown++;
                $sumocvdown  += $ivfield{$voltlabel};
                $sumtempdown += $ivfield{$templabel};
            }
        }
    }
    $ocvavg      = -32768;
    $tempavg     = -32768;
    $ocvavgup    = -32768;
    $tempavgup   = -32768;
    $ocvavgdown  = -32768;
    $tempavgdown = -32768;
    $ocvavg      = $sumocv / $iocv if ($iocv);
    $tempavg     = $sumtemp / $iocv if ($iocv);
    $ocvavgup    = $sumocvup / $iocvup if ($iocvup);
    $tempavgup   = $sumtempup / $iocvup if ($iocvup);
    $ocvavgdown  = $sumocvdown / $iocvdown if ($iocvdown);
    $tempavgdown = $sumtempdown / $iocvdown if ($iocvdown);
}

sub callcalc {
    $ivimax = 0;
    for ( $i = 0 ; $i < $#ivdata ; $i++ ) 
    {
        @Fld = split ( ' ', $ivdata[$i], 9999 );
        for ( $ii = 2 ; $ii <= $#Fld ; $ii += 2 ) {
            $ivfield{ $Fld[$ii] } = $Fld[ $ii + 1 ];
        }
	### Set fields to 0 if below cutoff values   ###
	for my $g ('h2','o2','air','o2_cathode','n2_cathode','co','co2','ch4','n2','ar','he','nh3','backup')
	{
	    next unless (exists($ivfield{$g}));
	    $ivfield{$g} = 0 if ($ivfield{$g} < $cutoff{$g});
	}
	### Allow for amonia in fuel gas ###
	$ivfield{'h2'} += $ivfield{'nh3'} * 3 / 2;
	$ivfield{'n2'} += $ivfield{'nh3'} / 2;
	### Allow for backup gas                     ###
	$ivfield{'h2'} += $ivfield{'backup'} * $backup_h2_conc;
	$ivfield{'n2'} += $ivfield{'backup'} * (1 - $backup_h2_conc);
	### Make sure that a tiny amount if H2 is present to awoid errors #####
	$ivfield{'h2'} = 1e-10 unless ($ivfield{'h2'});
	### Allow for carbon containing gasses       ###
	my $ch4cmd = '';
	$ch4cmd = ' --use_ch4 YES' if ($ivfield{'ch4'} || $ivfield{'co2'} || $ivfield{'co'});
	if ($ch4cmd)
	{
	    $ch4cmd .= ' --CH4 '.$ivfield{'ch4'} if ($ivfield{'ch4'});
	    $ch4cmd .= ' --CO '.$ivfield{'co'} if ($ivfield{'co'});
	    $ch4cmd .= ' --CO2 '.$ivfield{'co2'} if ($ivfield{'co2'});
	}
        $h2flowcmd = " --H2 " . $ivfield{'h2'};
	my $inert = 0;
	foreach ('n2','ar','he')
	{
	    $inert += $ivfield{$_} if exists $ivfield{$_};
	}
	$h2flowcmd .= " --N2 $inert" if ($inert);
	if (exists $ivfield{'h2o'} && $ivfield{'h2o'})
	{
	    $h2flowcmd .= " --H2O $ivfield{'h2o'}";
	}
        $o2addcmd = " --O2_add " . $ivfield{'o2'};
	### Allow for mixtures of air and pure oxygen at cathode ####
	my $aircmd = ' --Air '.$ivfield{'air'};
	$aircmd .= " --O2_cathode $ivfield{'o2_cathode'}" if ($ivfield{'o2_cathode'});
	$aircmd .= " --N2_cathode $ivfield{'n2_cathode'}" if ($ivfield{'n2_cathode'});
	$aircmd .= " --O2_air $ivfield{'o2_air'}" if ($ivfield{'o2_air'});
	### Allow for dry gas                         ###
	my $watercmd = ' --water 0';
	$watercmd = ' --water '.$ivfield{'bottle_temp'} if ($ivfield{'bottle_temp'} > 0);
	my $wet = $ivfield{'bottle_temp_enabled'}; 
	if (defined($ivfield{'bottle_temp_anode_enabled'}))
	{
	    $wet = $ivfield{'bottle_temp_anode_enabled'};
	}
	if (defined($wet) && $wet == 0)
	{
	    $watercmd .= " --dry 1";
	} 
	my $P = 1;
	$P = $ivfield{$presslabel} if (exists($ivfield{$presslabel}));
        $ivfield{$currentlabel} = 0 if (abs($ivfield{$currentlabel}) < $currentepsilon);
        $cstr =
          '/usr/local/bin/OCV_corr --command par_all --valid yes --cell '
          . $ivfield{$templabel}
          . " --Tleak "
          . $tempavgup
	  . $watercmd
          . $h2flowcmd
          . $aircmd
          . $o2addcmd 
	  . ' --I '. $ivfield{$currentlabel}
	  . ' --P '. $P
          . ' --U -' . $ivfield{$voltlabel} / 1000.0
          . ' --emf -'. $ocvavgup / 1000.0 . " --A "
          . $area
          . $ch4cmd;
	$ivimax = $ivfield{$currentlabel} if (abs($ivfield{$currentlabel}) > abs($ivimax));
        print $cstr, "\n" if ($debug);
        @res = `$cstr`;
        &writedata();
    }
}

sub writedata {
    $currdens = $ivfield{$currentlabel} / $area;
    $currdens = $currdens > 0 ? $currdens : 0;
    chomp( $ivdata[$i] );
    print OUTFILE $ivdata[$i], "  ";
    for (@res) {
	s/nan/-32768/g;
        chomp($_);
        @Fld = split ( ' ', $_, 9999 );
        if ( $#Fld > 0 ) { print OUTFILE $_, " "; }
    }
    print OUTFILE "\n";

}

sub printavgvalues {
#    for ( "T_center", "h2","o2", "air", "ch4", "backup", "sweep" ) {
    for ('T_center','T_corner',@gaslst) 
    {
        print IVAVGTABLE $_, " ", max(0,$ivfieldsum{$_} / $#ivdata), " ";
    }
    print IVAVGTABLE " ocvavg ",        $ocvavg;
    print IVAVGTABLE " tempavg ",       $tempavg;
    print IVAVGTABLE " ocvavgup  ",     $ocvavgup;
    print IVAVGTABLE " tempavgup ",     $tempavgup;
    print IVAVGTABLE " ocvavgdown  ", $ocvavgdown;
    print IVAVGTABLE " tempavgdown ",   $tempavgdown;
    print IVAVGTABLE "\n";

}

sub split_up_down {
    $cstr =
      "/bin/awk \'NR<=("
      . $tabledata{'ncmax'} . "-"
      . $tabledata{'nstart'}
      . "+1)\' "
      . $outfile . " > "
      . $outfile . "_up";
    print $cstr, "\n" if ($debug);

    system($cstr);
    $cstr =
      "/bin/awk \'NR>=("
      . $tabledata{'ncmax'} . "-"
      . $tabledata{'nstart'}
      . "+1)\' "
      . $outfile . " > "
      . $outfile . "_down";
    print $cstr, "\n" if ($debug);
    system($cstr);
}

sub get_result_fields {

    $cstr = "head -1 $outfile";
    @line1 = split ( " ", `$cstr` );
    for ( $i2 = 2 ; $i2 <= $#line1 ; $i2 += 2 ) {

        chomp( $line1[$i2] );
        $ylabel = $line1[$i2];
        $col{$ylabel} = $i2 + 2;

    }
}

sub make_sorted_power_and_r_sec_files {
    for ( "Power", "R_secant" ) {
	my $currentcalclimit=$tabledata{'cmax'}*$i_min_Rmin_calc;
        $resfile = $outdir . "/" . $_;
        $cstr    =
          "awk '\$"
          . $col{$_}
          . ">0&&\$"
          . $col{$currentlabel} . ">"
          . $currentcalclimit
          . "{print \$"
          . $col{$_}
          . ", \$0}' $outdir"
          . "/ivdata_up | sort -n > $resfile";
        $cstr    =
          "awk '\$"
          . $col{$_}
          . ">0&&\$"
          . $col{$currentlabel} . "<"
          . -$currentcalclimit
          . "{print \$"
          . $col{$_}
          . ", \$0}' $outdir"
          . "/ivdata_up | sort -n > $resfile" if ($ivimax < 0);
        $cstr    =
          "awk '\$"
          . $col{$_}
          . "<0&&\$"
          . $col{$currentlabel} . "<"
          . -$currentcalclimit
          . "{print \$"
          . $col{$_}
          . ", \$0}' $outdir"
          . "/ivdata_up | sort -n > $resfile" if (($ivimax < 0) && ($_ eq 'Power'));

        system($cstr);
    }
};

sub make_r_sec_files_vs_cell_voltage_and_current_for_interpolation {
    for ( $voltlabel, $currentlabel ) {
        $resfile = $outdir . "/" . $_ . "_R_secant";
        $cstr    =
          "/bin/awk '\$"
          . $col{$_}
          . ">0&&\$"
          . $col{$currentlabel} . ">"
          . $currentepsilon
          . "{print \$"
          . $col{$_} . ", \$"
          . $col{"R_secant"}
          . "}' $outdir"
          . "/ivdata_up > $resfile";

        $cstr    =
          "/bin/awk '\$"
          . $col{$_}
          . ">0&&\$"
          . $col{$currentlabel} . "< -"
          . $currentepsilon
          . "{print \$"
          . $col{$_} . ", \$"
          . $col{"R_secant"}
          . "}' $outdir"
          . "/ivdata_up > $resfile" if ($ivimax < 0);

        $cstr    =
          "/bin/awk '\$"
          . $col{$currentlabel} . "< -"
          . $currentepsilon
          . "{print \$"
          . $col{$_} . ", \$"
          . $col{"R_secant"}
          . "}' $outdir"
          . "/ivdata_up > $resfile" if( ($ivimax < 0) && ($_ eq 'current'));

	system($cstr);
    }

}

sub getstartvalues_current_gt_eps {
    $resfilename = "rstartvalues";
    $resfile     = $outdir . "/" . $resfilename;
    $cstr        =
      "/bin/awk '\$"
      . $col{"R_secant"}
      . ">0&&\$"
      . $col{$currentlabel} . ">"
      . $currentepsilon
      . "{print \$0"
      . "}' $outdir"
      . "/ivdata_up | head -1 >  $resfile";
    $cstr        =
      "/bin/awk '\$"
      . $col{"R_secant"}
      . ">0&&\$"
      . $col{$currentlabel} . "<"
      . -$currentepsilon
      . "{print \$0"
      . "}' $outdir"
      . "/ivdata_up | head -1 >  $resfile" if ($ivimax < 0);

    system($cstr);
    $cstr = "cat $resfile  | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir" . "/$resfilename";
    system($cstr);

}

sub get_min_max_values {
    $resfilename = "rminvalues";
    $resfile     = $outdir . "/" . $resfilename;

    $cstr = "head -1        $outdir" . "/R_secant > $resfile";
    system($cstr);
    $cstr = "cat $resfile  | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir" . "/$resfilename";
    system($cstr);

    $resfilename = "powermaxvalues";
    $resfile     = $outdir . "/" . $resfilename;

    $cstr = "tail -1        $outdir" . "/Power > $resfile";
    system($cstr);
    $cstr = "cat $resfile  | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir" . "/$resfilename";
    system($cstr);

    $resfilename = "imaxvalues";
    $resfile     = $outdir . "/" . $resfilename;

    $cstr = "tail -1        $outdir" . "/ivdata_up > $resfile";
    system($cstr);
    $cstr = "cat $resfile  | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir" . "/$resfilename";
    # get imaxdata 
    system($cstr);
    open( RESFILE, $resfile );
    $imaxline = <RESFILE>;
    close(RESFILE);
    @imaxline1 = split ( " ", $imaxline );
    for ( $ii4 = 2 ; $ii4 <= $#imaxline1 ; $ii4 += 2 ) {
        $imaxdata{ $imaxline1[$ii4] } = $imaxline1[ $ii4 + 1 ];
    }

}

sub interpolate_resistance_current_values {
    for (@resistance_current_values) {
        $cval = $_ * $area;
        $cval = -$_ * $area if ($ivimax < 0);
        $cstr =
          "perl /usr/local/bin/lineinterpol.pl $outdir"
          . "/current_R_secant $cval > 	 $outdir"
          . "/current_"
          . $_;
        system($cstr);
        $cstr =
          "cat $outdir" . "/current_" . $_ . " | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir" . "/current_" . $_;
        system($cstr);

    }

    $cval = $imaxdata{"current"} * 2.0 / 3.0;
    $cstr =
      "perl /usr/local/bin/lineinterpol.pl $outdir"
      . "/current_R_secant $cval > 	 $outdir"
      . "/current_2_div_3_imax";
    system($cstr);
    $cstr =
      "cat $outdir"
      . "/current_2_div_3_imax | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir"
      . "/current_2_div_3_imax";
   system($cstr);

    $cval = $predominant_current * $area;
    $cstr =
      "perl /usr/local/bin/lineinterpol.pl $outdir"
      . "/current_R_secant $cval > 	 $outdir"
      . "/predominant_current";
    system($cstr);

    $cstr =
      "cat $outdir"
      . "/predominant_current | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir"
      . "/predominant_current";
    system($cstr);

    $cstr =
      "perl /usr/local/bin/lineinterpol.pl $outdir"
      . "/cell_voltage_R_secant 750 > 	 $outdir"
      . "/R_750_mV";
    system($cstr);

    $cstr = "cat $outdir" . "/R_750_mV | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir" . "/R_750_mV";
    system($cstr);

}

sub interpolate_voltage_current_values {
    for (@current_values) {
        $cval = $_ * $area;
        $cval = -$_ * $area if ($ivimax < 0);
        $cstr =
          "perl /usr/local/bin/lineinterpol.pl $outdir"
          . "/cell_voltage_vs_current $cval > 	 $outdir"
          . "/current_voltage_"
          . $_;
        system($cstr);
        $cstr =
          "cat $outdir"
          . "/current_voltage_"
          . $_
          . "  | awk 'NF>1{print ; n++};END{ if (n==0) print \"\"}' >> $plotdir"
          . "/current_voltage_"
          . $_;
        system($cstr);
    }
}


sub max {
    local($a, $b) = @_;
    ($a gt $b ? $a : $b);      
}
