#!/usr/bin/perl
# $Id: pO2_leak,v 1.1 2011/07/05 08:08:19 sofc Exp $
my $VERSION = 0.2;
my $PROGRAM = 'pO2_leak';
use constant F => 96485;
use constant R => 8.314;
use constant p0 => 1;
my $debug = 0;
use strict;


foreach (@ARGV)
{
    next unless (/--help/);
    &help;
    exit;
}

for (my $x = 0; $x < scalar(@ARGV) ; $x++)
{
    if ($ARGV[$x] =~ /--version/)
    {
	print "$PROGRAM is: $VERSION\n";
	exit;
    }
}


my %input = &get_input(@ARGV);
if ($input{'debug'})
{
    $debug = 1;
    foreach (sort keys %input)
    {
	next if (/^debug$/);
	print $_,' : ',$input{$_},"\n";
    }
}

our $atm = defined($input{'gas'}) ? $input{'gas'} : 1;
our $watertemp = defined($input{'water'}) ? $input{'water'}+273.15 : 273.15;
our $celltemp = defined($input{'cell'}) ? $input{'cell'}+273.15 : 1273.15;
# Flow is measured in L/h !!!
our $Arflow = defined($input{'flow'}) ? $input{'flow'} : 1;
our $ArO2 = defined($input{'ArO2'}) ? $input{'ArO2'} : 1e-20;
our $H2flow = defined($input{'H2flow'}) ? $input{'H2flow'} : 0;
our $O2flow = defined($input{'O2_add'}) ? $input{'O2_add'} : 0;
our $dry = defined($input{'dry'}) ? $input{'dry'} : 1; ## Default dry gas ###

# Coefficients for the water partial pressure are obtained by fitting a 6-
# power function to data from 'Databog Fysik Kemi', F og K forlaget 10.udgave 
my @a;
$a[6] = 6.3096E-11;
$a[5] = 2.5259E-6;
$a[4] = -3.2193E-3;
$a[3] = 1.6322;
$a[2] = -414.9;
$a[1] = 52920;
$a[0] = -2.7085E6;
# End ref
my $ph2o = 0;
for (my $x=0; $x<7; $x++)
{
    my $test = $watertemp;
    for (my $y=1;$y<$x;$y++)
    {
	$test = $test* $watertemp;
    }
    if ($x==0){$test = 1;};
    $ph2o += $a[$x]* $test;
} 

$ph2o = 1.0E-19 if ($dry);

our $command = 0;
our $showall = 0;
if (defined($input{'command'}))
{
    if ($input{'command'} =~ /all/) 
    {
	$showall = 1;
    }
    if ($input{'command'} =~ /po2/)
    {
	$command = 4;
    }
    if ($input{'command'} =~ /I/)
    {
	$command = 7;
    }
}


#####  Formulas  #####

# log(Kp) = 2.958-13022/T (from Hartung, see below)
# P_O2 = Kp^2 * (P_H2O / P_H2)^2  according to eqlibrium-function 
# Emf = (RT/4F)*ln(P_O2'/P_O2'')  versus air, according to Nernst
# P * V = n * R * T  Ideal gas law
# I = 4 * n * F  Faradays law for electrolysis for O2
#####  OCV calculation #######  
$ph2o = $ph2o/100000;
#  log(Kp) is according to R. Hartung and H.-H. Mobius:
#  "Potentiometrische Bestimmung des Wasserdampf
#  Dissoziationsgleichgewichtes zwischen 1000 und
#  1300K mit einer Festelektrolytzelle",
#  Chemie-ing.-techn. 40-12 pp592-600, 1968 
our $logKp = 2.958 - 13022/$celltemp; 
#  End ref
our $ph2 = $atm;

if( defined($input{'pH2O'})) 
{ 
    $ph2o = $input{'pH2O'}+0;
}
our $Kp = 10**$logKp;
our $nH2 = $H2flow * $atm / (60 * 60 * 0.0821 * 273.15);
our $nH2O = $H2flow * $ph2o / (60 * 60 * 0.0821 * 273.15 * (1-$ph2o));
our $nO2 = 0;
if ($nH2 > 0 && $O2flow > 0)
{
    $nO2 = $O2flow / (60 * 60 * 0.0821 * 273.15);
    $nH2O = $nH2O + 2 * $nO2;
    $nH2 = $nH2 - 2 * $nO2; 
}
else
{
    $nO2 = $Arflow * $atm * $ArO2 / (60 * 60 * 0.0821 * 273.15);
}
our ($ph2_,$ph2o_) = (0,0);
if ($nH2 > 0)
{
    $ph2_ = $nH2 / ($nH2 + $nH2O);
    $ph2o_ = $nH2O / ($nH2 + $nH2O);
}
our $pO2 = 0;
if ($nH2)
{
    $pO2 = $Kp * $Kp * $nH2O * $nH2O / ($nH2 * $nH2 );
}
else
{
    $pO2 = $ArO2 * $atm;
}
our $latm = log(0.21 / $pO2);
our $OCV = -$latm * R * $celltemp / (4 * F);

our $Em = defined($input{'emf'}) ? $input{'emf'} : $OCV;
#### Leak calculation based on measured EMF ($Em) #####
our $po2m = 0.21* exp( 4* F * $Em / (R * $celltemp));

our ($Z,$t,$deltanH,$x,$IO2,$pH2o,$pH2Oo);
if ($nH2)
{
    $Z = sqrt($po2m)/$Kp;
    $t = ($Z * $nH2 - $nH2O) / (2 + 2 * $Z);
# $x is the leak in percent of the H2 flow! 
#### Leak current calculation, Current in A!!!   ####
    $deltanH = 2* $t;
    $x = 100 * $deltanH / $nH2; 
    $IO2 = 4 * F * $t;
    $pH2o = ($nH2-$deltanH)/($nH2+$nH2O);
    $pH2Oo = ($nH2O+$deltanH)/($nH2+$nH2O);
    if ($showall)
    {
	print "OCV:\n";
	print "pH2O = ",$ph2o_,",  pH2 = ",$ph2_,",  pO2 = ",$pO2,"\n";
	print "OCV: ",$OCV," V\n";
	print "Real:\n";
	print "pH2O = ",$pH2Oo,",  pH2 = ",$pH2o,",  pO2 = ",$po2m,"\n";
	print "EMF: ",$Em," V\n";
	print "Oxygen leak = ",$x," % of H2 flow\n";
	print "Leak current = ",$IO2," A for a H2 flow of ",$H2flow," L/h\n";
	print "All calculations based on a cell temperature of ",$celltemp," K\n";
	print "and an OCV-water vapour pressure determined by eqlibrium\n";
	print "with liquid water at ",$watertemp," K\n";
    }
}
else
{
    my $lnO2 = $Arflow * $atm * $po2m / (60 * 60 * 0.0821 * 273.15);
    $IO2 = 4 * F * ($lnO2-$nO2);
    if ($showall)
    {
	print "OCV:\n";
	print "OCV: ",$OCV," V\n";
	print "Real:\n";
	print "EMF: ",$Em," V\n";
	my $lpO2 = ($po2m-$pO2)*1e6;
	print "Leak = $lpO2 ppm O2\n";
	my $lIO2 = $IO2*1000;
	print "Leak current = ",$lIO2," mA for a Ar flow of ",$Arflow," L/h\n";
	print "All calculations based on a cell temperature of ",$celltemp," K\n";
    }
}
#### Output of calculations ########

if ($command == 4)
{
    print $po2m,"\n";
    exit 1;
}
if ($command == 7)
{
    print $IO2,"\n";
    exit 1;
}

if ($command == 0)
{
    if (!$showall)
    {
	if ($nH2 > 0)
	{
	    print "OCV = ",$Em,",  Oxygen leak = ",$x," % of H2 flow\n";
	    print "Leak current = ",$IO2," A\n";
	}
	else
	{
	    my $lpO2 = $po2m*1e6;
	    print "OCV = ",$Em,",  Oxygen leak = ",$lpO2," ppm of Ar flow\n";
	    my $lIO2 = $IO2*1000;
	    print "Leak current = ",$lIO2," mA for a Ar flow of ",$Arflow," L/h\n";
	}
    }
}
exit 1;

sub get_input
{
    my %out = ();
    my @input = @_;
    for (my $x = 0; $x < scalar(@input);$x++)
    {
	if ($input[$x] =~ /^*--/)
	{
	    $input[$x] =~ s/^*--//;
	    $input[$x+1] =~ s/^*\s//;
	    $out{$input[$x]} = $input[$x+1];
	    $x++;
	}
    }
    return %out;
}

sub help
{
    print "\n\n";
    print "The $PROGRAM calculates the leak curent and leak oxygen partial pressure for\n";
    print "oxygen senosrs. The default gas supply is air and dry argon but gas mixtures\n";
    print "containing hydrogen and water wapor can also be used (use the --H2flow input\n";
    print "to force the porgram to use hydrogen-water equlibrium instead of simple concentration\n";
    print "cell calculations).\n\n";
    print "Leak  Usage:\n";
    print "leak --INPUT VALUE\n\n";
    print "  INPUT is the command for which the VALUE is the corresponding input value.\n\n";
    print "     --command : forces output into the following formats:\n";
    print "          all  : All values are displayed (verbose output).\n";
    print "          I    : Outputs leak current in A\n";
    print "          po2  : Outputs only the oxygen partial pressure.\n";
    print "     --flow    : Inputs the Argon flow in L/h, default is 1 l/h.\n";
    print "     --emf     : Inputs the sensor emf, default is theoretical Emf.\n\n";
    print "     --cell    : Inputs the sensor temperature, default is 1000 C.\n\n";
    print "     --ArO2    : Inputs the oxygen content of the input argon. Default is 1e-20\n";
    print "     --dry     : Indicates if gas is dry (0 for wet, 1 for dry, default is dry)\n";
    print "                 This and the below options only applies if H2 is used instead of Ar\n";
    print "     --water   : inputs the water temperature, default is 0 C.\n\n";
    print "     --H2flow  : Inputs the hydrogen flow in L/h, default is 0 l/h.\n";
    print "     --O2_add  : Inputs the oxygen flow to the anode gas in l/h,\n";
    print "                 default is 0 l/h.\n";
    print "                 Note that this has to be at 0 degree C!!\n\n";
    print "     --gas     : Inputs the hydrogen gas composition.\n";
    print "                 Default is 1, coresponding to 100\% hydrogen\n";
    print "                 before equlibrium with liquid water.\n\n";
    print "     --pH2O    : Inputs the water partial pressure of the gas if this\n";
    print "                 this is not determined by equlibrium with liquid water.\n\n";
}
