// $Id: gas.cpp,v 1.5 2025/11/27 09:42:32 sqko Exp $
#include "gas.hpp"
#include <math.h>
#include <stdio.h>
#include "pstream.h"
#include <stdexcept>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/algorithm/string/join.hpp>

using std::string;
using std::iterator;
using namespace std;

double gas::equal_cutoff = 1E-30;
double gas::O2_Air = 0.21;
double gas::carbon_cutoff = 1E-50;
double gas::oxygen_anode_cutoff = 1E-50;
const double gas::F = 96485;
const double gas::R = 8.31;

// internal functions and variables

const double R_igl = 0.0821;
const double t0 = 273.15;

bool space(char c)
{
  return isspace(c);	
}

bool not_space(char c)
{
  return !isspace(c);	
}

// returns the first number after the identifyer specified
double find_value(const std::string & input, const std::string & match)
{
  typedef std::string::const_iterator iter;
  iter i = input.begin();
  std::size_t found = input.find(match);
  if (found == std::string::npos)
    {
      // return obvious wrong value if search string not found
      return -32768;	
    }
  for (std::size_t x = 0; x != found ; ++x)
    {
      ++i;	
    }
  for (iter x = match.begin(); x != match.end(); ++x)
    {
      ++i;	
    }
  i = find_if(i, input.end(), not_space);
  iter j = find_if(i,input.end(), space);
  return atof(std::string(i,j).c_str());
}


double Ltomol(double L, double p)
{
  return L * p / (60 * 60 * R_igl * t0);
}

double moltoL(double mol, double p)
{
  return mol * 60 * 60 * R_igl * t0 / p;	
}

double p_water(double temp)
{
  /*
    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
  */
  static const double waterc[] = {-2.7085E+6 ,52920.0 ,-414.9 ,1.6322 ,-3.2193E-3 ,2.5259E-6 ,6.3096E-11};
  static const size_t n_waterc = sizeof(waterc)/sizeof(*waterc);
  double p = 0;
  for (size_t i = 0; i < n_waterc; ++i)
    {
      p += waterc[i] * pow(temp,i);
    }
  return p/100000;	
}

// static class functions

double gas::water(double temp,double flow)
{
  double pw = p_water(temp);
  return flow * pw / (1 - pw);
}

double gas::hartung(double t)
{
  /*
    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 
  */
  double lKp = 2.958-13022/t;
  return pow(10,lKp);	
}


// member functions

double gas::Xgas(const gname gasname) const
{
  double Ptot = pres_.H2 + pres_.H2O + pres_.N2_anode + pres_.O2_anode + pres_.CO + pres_.CO2;
  double X = 0.0;
  switch(gasname) {
  case H2 :
    X = pres_.H2 / Ptot;
    break;
  case H2O : 
    X = pres_.H2O / Ptot;
    break;
  case CO :
    X = pres_.CO / Ptot;
    break;
  case CO2 : 
    X = pres_.CO2 / Ptot;
    break;
  case CH4 : 
    X = pres_.CH4 / Ptot;
    break;
  case O2_anode : 
    X = pres_.O2_anode / Ptot;
    break;
  case N2_anode : 
    X = pres_.N2_anode / Ptot;
    break;
  case O2_cathode : 
    X = pres_.O2_cathode / (pres_.O2_cathode + pres_.N2_cathode);
    break;
  case N2_cathode : 
    X = pres_.N2_cathode / (pres_.O2_cathode + pres_.N2_cathode);
    break;
  }
  return X;
}

double gas::emf()
{
  if (valid_emf_)
    {
      return emf_;
    }
  calc_emf();
  return emf_;
}

double gas::get_leak(const double emf)
{
  // Do nothing and return 0 if the input emf and the theoretical are the same
  if (!valid_emf_)
    calc_emf();
  if (emf == emf_)
    return 0;	
  if (comp_.CH4 < gas::carbon_cutoff && comp_.CO < gas::carbon_cutoff && comp_.CO2 < gas::carbon_cutoff)	
    {
      // If no carbon containing gasses, use nernst and hartung derectly
      double po2 = pres_.O2_cathode * exp(4 * gas::F * emf/(gas::R * temp_));
      double z = pow(po2,0.5)/hartung(temp_);
      return gas::F * 4 * (z *  comp_.H2 - comp_.H2O )/(2 + 2 * z);
    }
  else
    {
      const double deltaI = 0.0001;
      const double cutoff = 0.0001 * fabs(emf) / 100;
      double I = 0;
      gas d1(*this);
      gas d2(*this);
      double delta = emf - d1.emf();
      int iter = 0;
      while (fabs(delta) > cutoff)
	{
	  ++iter;
	  d1 = *this;
	  d1.current(I,skip_cathode);
	  d2 = *this;
	  d2.current(I+deltaI,skip_cathode);
	  double deltay = d2.emf() - d1.emf();
	  double alfa = deltay / deltaI;
	  delta = emf - d1.emf();
	  if (alfa != 0)
	    {
	      double dx = delta / alfa;
	      I += dx;		
	    }
	  // make sure that ieration does not run wild and return 0 if so
	  if (iter > 10)
	    {
	      return 0;	
	    }
	}
      return I;
    }
}


void gas::calc_pres()
{
  double cathode = comp_.O2_cathode + comp_.N2_cathode;
  double anode = comp_.H2 + comp_.CO + comp_.CH4 + comp_.O2_anode + comp_.N2_anode + comp_.H2O + comp_.CO2;
  pres_.H2 = comp_.H2 * P_/ anode;
  pres_.O2_cathode = comp_.O2_cathode * P_/ cathode;
  pres_.CO = comp_.CO * P_/ anode;
  pres_.CO2 = comp_.CO2 * P_/ anode;
  pres_.N2_cathode = comp_.N2_cathode * P_/ cathode;
  pres_.N2_anode = comp_.N2_anode * P_/ anode;
  pres_.O2_anode = comp_.O2_anode * P_/ anode;
  pres_.CH4 = comp_.CH4 * P_/ anode;
  pres_.Air = 0;
  pres_.H2O = comp_.H2O * P_/ anode;
  //  calc_emf();
  valid_emf_ = false;
}

void gas::react_gasses()
{
  if (mode_ == L)
    {
      to_mol();	
    }
  // first react oxygen with H2 followed by CO if O2 in surplus
  if (comp_.O2_anode > 0)
    {
      if (comp_.O2_anode < comp_.H2 / 2)
	{
	  comp_.H2 -= 2 * comp_.O2_anode;
	  comp_.H2O += 2 * comp_.O2_anode;
	  comp_.O2_anode = 0;	
	}
      else
	{
	  comp_.O2_anode -= comp_.H2/2;
	  comp_.H2O += comp_.H2;
	  comp_.H2 = 1E-100;
	  if (comp_.O2_anode < comp_.CO / 2)
	    {
	      comp_.CO -= 2 * comp_.O2_anode;
	      comp_.CO2 += 2 * comp_.O2_anode;
	      comp_.O2_anode = 0;	
	    }
	  else
	    {
	      comp_.O2_anode -= comp_.CO / 2;
	      comp_.CO2 += comp_.CO;
	      comp_.CO = 0;
	    }	
	}	
    }
  // do methane conversion 
  if (comp_.CH4 > gas::carbon_cutoff)
    {
      // First use any oxygen left to react directly with CH4
      // CH4 + O2 -> CO2 + 2 H2
      if (comp_.CH4 < comp_.O2_anode)
	{
	  comp_.CO2 += comp_.CH4;
	  comp_.H2O += 2 * comp_.CH4;
	  comp_.O2_anode -= comp_.CH4;
	  comp_.CH4 = 0;
	}
      else
	{
	  comp_.CH4 -= comp_.O2_anode;
	  comp_.CO2 += comp_.O2_anode;
	  comp_.H2 += 2 * comp_.O2_anode;
	  comp_.O2_anode = 0;	
	  // Then react with H2O: (CH4 + H2O -> 3 H2 + CO)
	  if (comp_.H2O > comp_.CH4)
	    {
	      comp_.H2 += 3 * comp_.CH4;
	      comp_.H2O -= comp_.CH4;
	      comp_.CO += comp_.CH4;
	      comp_.CH4 = 0;
	    }
	  else
	    {
	      // use all water first
	      comp_.H2 += 3 * comp_.H2O;
	      comp_.CH4 -= comp_.H2O;
	      comp_.CO += comp_.H2O;
	      comp_.H2O = 1E-100;
	      if (comp_.CO2 > comp_.CH4)
		{
		  // React remaining CH4 with CO2 (CH4 + CO2 -> 2 H2 + 2 CO)
		  comp_.H2 += 2 * comp_.CH4;
		  comp_.CO += 2 * comp_.CH4;
		  comp_.CO2 -= comp_.CH4;
		  comp_.CH4 = 0;
		}
	      else
		{
		  throw std::domain_error("Not enough O2, H2O or CO2 to react all CH4");
		}
	    }
	}
    }
  // second round of oxygen reaction if more H2 and/or CO has been created from CH4
  // and O2 was in surplus from first conversion 
  // makes it possible to use more vide gas compositions
  if (comp_.O2_anode > 0)
    {
      if (comp_.O2_anode < comp_.H2 / 2)
	{
	  comp_.H2 -= 2 * comp_.O2_anode;
	  comp_.H2O += 2 * comp_.O2_anode;
	  comp_.O2_anode = 0;	
	}
      else
	{
	  comp_.O2_anode -= comp_.H2/2;
	  comp_.H2O += comp_.H2;
	  comp_.H2 = 1E-100;
	  if (comp_.O2_anode < comp_.CO / 2)
	    {
	      comp_.CO -= 2 * comp_.O2_anode;
	      comp_.CO2 += 2 * comp_.O2_anode;
	      comp_.O2_anode = 0;	
	    }
	  else
	    {
	      comp_.O2_anode -= comp_.CO / 2;
	      comp_.CO2 += comp_.CO;
	      comp_.CO = 0;
	    }	
	}	
    }
  calc_pres();	
}

void gas::calc_emf()
{
  emf_ = 0;
  if (mode_ == L)
    {
      to_mol();	
    }
  if (comp_.CH4 < gas::carbon_cutoff && comp_.CO < gas::carbon_cutoff && comp_.CO2 < gas::carbon_cutoff)	
    {
      double pO2 = pow(hartung(temp_),2) * comp_.H2O * comp_.H2O / (comp_.H2 * comp_.H2);
      if (pres_.O2_anode > gas::oxygen_anode_cutoff)
	{
	  pO2 = pres_.O2_anode;	
	}
      else
	{
	  // Set anode oxygen partial pressure to result of calculation
	  pres_.O2_anode = pO2;
	}
      emf_ = -log(pres_.O2_cathode/pO2) * gas::R * temp_ / (4 * gas::F);
      valid_emf_ = true;
    }
  else
    {
      double factor = 0.9999; 
      // factor nescesarry to awoid mole fractions to add up to more than 1 
      // Generate arguments to ch4_arg
      std::vector<std::string> argv;
      // first argument is discarded, don't know why, so populate with dummy
      argv.push_back("/usr/local/bin/Reforming_delG_Min");
      char tmp[20];
      sprintf(tmp,"--temp %.5f",temp_);
      argv.push_back(tmp);
      sprintf(tmp,"--P %.5f",P_);
      argv.push_back(tmp);
      double lh = pres_.H2*factor/P_;
      if (lh < 1E-10)
	lh = 1E-10;	
      sprintf(tmp,"--H2 %.10f",lh);
      argv.push_back(tmp);
      lh = pres_.H2O*factor/P_;
      if (lh < 1E-10)
	lh = 1E-10;	
      sprintf(tmp,"--H2O %.10f",lh);
      argv.push_back(tmp);
      sprintf(tmp,"--CO %.10f",pres_.CO*factor/P_);
      argv.push_back(tmp);
      sprintf(tmp,"--CO2 %.10f",pres_.CO2*factor/P_);
      argv.push_back(tmp);
      sprintf(tmp,"--CH4 %.10f",pres_.CH4*factor/P_);
      argv.push_back(tmp);
      sprintf(tmp,"--O2 %.10f",pres_.O2_anode*factor/P_);
      argv.push_back(tmp);
      sprintf(tmp,"--command");
      argv.push_back(tmp);
      sprintf(tmp,"par_all");
      argv.push_back(tmp);
      string joinedString = boost::algorithm::join(argv, " ");
      std::string matchs;
      std::string result;
      redi::ipstream in(joinedString);
      std::getline(in,result);
      std::getline(in,result);
      std::getline(in,result);
      matchs = "CH4_fraction";
      pres_.CH4 = find_value(result,matchs) * P_;
      std::getline(in,result);
      std::getline(in,result);
      matchs = "H2O_fraction";
      pres_.H2O = find_value(result,matchs) * P_;
      std::getline(in,result);
      matchs = "H2_fraction";
      pres_.H2 = find_value(result,matchs) * P_;
      std::getline(in,result);
      matchs = "CO_fraction";
      pres_.CO = find_value(result,matchs) * P_;
      std::getline(in,result);
      matchs = "CO2_fraction";
      pres_.CO2 = find_value(result,matchs) * P_;
      std::getline(in,result);
      matchs = "O2_fraction";
      pres_.O2_anode = find_value(result,matchs) * P_;
      emf_ = -log(pres_.O2_cathode/pres_.O2_anode) * gas::R * temp_ / (4 * gas::F);
      valid_emf_ = true;
    }
}


void gas::current(double I, calc_mode mode)
{
  double dH = I / (2 * gas::F);
  double dO = I / (4 * gas::F);
  if (mode_ == L)
    {
      to_mol();	
    }
  // fuel cell mode
  if (I > 0)
    {
      if (dH < comp_.H2)
	{
	  comp_.H2O += dH;
	  comp_.H2 -= dH;
	  dH = 0;
	}
      else
	{
	  dH -= comp_.H2;
	  comp_.H2O += comp_.H2;
	  comp_.H2 = 1E-100;
	  if (dH < comp_.CO)
	    {
	      comp_.CO2 += dH;
	      comp_.CO -= dH;
	      dH = 0;
	    }
	  else
	    {
	      throw std::domain_error("Not enough H2 or CO to convert!");	
	    }
	}
      if (mode == do_cathode)
	{
	  if (dO < comp_.O2_cathode)
	    {
	      comp_.O2_cathode -= dO;
	    }
	  else
	    {
	      throw std::domain_error("Not enough O2 to convert!");					
	    }
	}
    }
  // electolyser mode
  if (I < 0)
    {
      if (fabs(dH) < comp_.H2O)
	{
	  comp_.H2 -= dH;
	  comp_.H2O += dH;
	  dH = 0;
	}
      else
	{
	  dH += comp_.H2O;
	  comp_.H2 += comp_.H2O;
	  comp_.H2O = 1E-100;
	  if (fabs(dH) < comp_.CO2)
	    {
	      comp_.CO2 += dH;
	      comp_.CO -= dH;
	      dH = 0;									
	    }
	  else
	    {
	      throw std::domain_error("Not enough H2O or CO2 to convert!");
	    }	
	}
      if (mode == do_cathode)
	{
	  comp_.O2_cathode -= dO;
	}
    }
  calc_pres();
}

void gas::display()
{
  std::streamsize prec = std::cout.precision();
  std::cout.precision(4);
  std::cout << "Anode gas composition:" << std::endl;
  std::cout << "H2:\t" << pres_.H2 << std::endl;			
  std::cout << "H2O:\t" << pres_.H2O << std::endl;			
  std::cout << "N2_anode:\t" << pres_.N2_anode << std::endl;			
  std::cout << "O2_anode:\t" << pres_.O2_anode << std::endl;			
  std::cout << "CO:\t" << pres_.CO << std::endl;			
  std::cout << "CO2:\t" << pres_.CO2 << std::endl;			
  std::cout << "CH4:\t" << pres_.CH4 << std::endl;	
  std::cout << "Cathode gas composition:" << std::endl;		
  std::cout << "N2:\t" << pres_.N2_cathode << std::endl;			
  std::cout << "O2:\t" << pres_.O2_cathode << std::endl;			
  std::cout << "Emf of gas:\t" << emf() << std::endl;
  std::cout << "Temperature:\t" << temp_ << std::endl;
  std::cout << "Pressure\t" << P_ << std::endl;
  std::cout.precision(prec);
}

void gas::to_mol()
{
  if(mode_ == L)
    {
      comp_.H2 = Ltomol(comp_.H2,P_);
      comp_.O2_cathode = Ltomol(comp_.O2_cathode,P_);
      comp_.CO = Ltomol(comp_.CO,P_);
      comp_.CO2 = Ltomol(comp_.CO2,P_);	
      comp_.CH4 = Ltomol(comp_.CH4,P_);
      comp_.N2_cathode = Ltomol(comp_.N2_cathode,P_);
      comp_.N2_anode = Ltomol(comp_.N2_anode,P_);
      comp_.O2_anode = Ltomol(comp_.O2_anode,P_);
      comp_.Air = Ltomol(comp_.Air,P_);
      comp_.H2O = Ltomol(comp_.H2O,P_);
      mode_ = mol;
    }
}

void gas::to_L()
{
  if (mode_ == mol)
    {
      comp_.H2 = moltoL(comp_.H2,P_);
      comp_.O2_cathode = moltoL(comp_.O2_cathode,P_);
      comp_.CO = moltoL(comp_.CO,P_);
      comp_.CO2 = moltoL(comp_.CO2,P_);
      comp_.CH4 = moltoL(comp_.CH4,P_);
      comp_.N2_cathode = moltoL(comp_.N2_cathode,P_);
      comp_.N2_anode = moltoL(comp_.N2_anode,P_);
      comp_.O2_anode = moltoL(comp_.O2_anode,P_);
      comp_.Air = moltoL(comp_.Air,P_);
      comp_.H2O = moltoL(comp_.H2O,P_);
      mode_ = L;
    }
}

double gas::max_current() const
{
  if (mode_ == mol)
    {
      double ia = comp_.H2 * 2 * gas::F;
      ia += comp_.CO * 2 * F;
      double ic = comp_.O2_cathode * 4 * gas::F;
      return ia < ic ? ia : ic;
    }
  else
    {
      gas test(*this);
      test.to_mol();
      return test.max_current();	
    }
}

double gas::min_current() const
{
  if (mode_ == mol)
    {
      double ia = comp_.H2O * 2 * gas::F;
      ia += comp_.CO2 * 2 * gas::F;
      return -ia;	
    }
  else
    {
      gas test(*this);
      test.to_mol();
      return test.min_current();
    }
}

// constructors

gas::gas(const gas & i)
:temp_(i.temp_),P_(i.P_),mode_(i.mode_),comp_(i.comp_)
{
  calc_pres();
}

gas::gas(double temp,double pressure,const gcomp & i)
:temp_(temp),P_(pressure),mode_(L),comp_(i)
{
  if (comp_.Air < 0)
    {
      comp_.Air = 0;
      std::cerr << "Air flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.H2 < 0)
    {
      comp_.H2 = 0;
      std::cerr << "H2 flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.CO < 0)
    {
      comp_.CO = 0;
      std::cerr << "CO flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.H2O < 0)
    {
      comp_.H2O = 0;
      std::cerr << "H2O flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.CO2 < 0)
    {
      comp_.CO2 = 0;
      std::cerr << "CO2 flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.CH4 < 0)
    {
      comp_.CH4 = 0;
      std::cerr << "CH4 flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.O2_anode < 0)
    {
      comp_.O2_anode = 0;
      std::cerr << "O2_anode flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.O2_cathode < 0)
    {
      comp_.O2_cathode = 0;
      std::cerr << "O2_cathode flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.N2_anode < 0)
    {
      comp_.N2_anode = 0;
      std::cerr << "N2_anode flow less than 0 setting to 0!" << std::endl;
    }
  if (comp_.N2_cathode < 0)
    {
      comp_.N2_cathode = 0;
      std::cerr << "N2_cathode flow less than 0 setting to 0!" << std::endl;
    }
  comp_.Air = 0;
  if (i.Air > 0)
    {
      comp_.O2_cathode += i.Air * gas::O2_Air;
      comp_.N2_cathode += i.Air * (1 - gas::O2_Air);		
    }
  calc_pres();
}

gas & gas::operator=(const gas & rhs)
{
  if (this != &rhs)
    {
      comp_ = rhs.comp_;
      temp_ = rhs.temp_;
      P_ = rhs.P_;
      emf_ = rhs.emf_;
      valid_emf_ = rhs.valid_emf_;
      pres_ = rhs.pres_;
      mode_ = rhs.mode_;
    }
  return *this;	
}

gas gas::operator+(const gas & rhs) const
{
  gas result = *this;
  result += rhs;
  return result;
}

bool gas::operator==(const gas & rhs) const
{
    if (this == &rhs)
      {
	return true;
      }
    else
      {
	bool res = true;
	if (fabs(comp_.H2 - rhs.comp_.H2) > gas::equal_cutoff || fabs(comp_.O2_cathode - rhs.comp_.O2_cathode) > gas::equal_cutoff)
	  res = false;
	if (fabs(comp_.CO - rhs.comp_.CO) > gas::equal_cutoff || fabs(comp_.CO2 - rhs.comp_.CO2) > gas::equal_cutoff)
	  res = false;
	if (fabs(comp_.CH4 - rhs.comp_.CH4) > gas::equal_cutoff || fabs(comp_.N2_cathode - rhs.comp_.N2_cathode) > gas::equal_cutoff)
	  res = false;
	if (fabs(comp_.N2_anode - rhs.comp_.N2_anode) > gas::equal_cutoff || fabs(comp_.O2_anode - rhs.comp_.O2_anode) > gas::equal_cutoff)
	  res = false;
	if (fabs(comp_.Air - rhs.comp_.Air) > gas::equal_cutoff || fabs(comp_.H2O - rhs.comp_.H2O) > gas::equal_cutoff)
	  res = false;
	return res;
      }
}

gas & gas::operator+=(const gas & rhs)
{
  if (this != &rhs)
    {
      if (P_ == rhs.P_ && mode_ == rhs.mode_ && temp_ == rhs.temp_ )
	{
	  if (mode_ == rhs.mode_)
	    {
	      comp_.H2 += rhs.comp_.H2;
	      comp_.O2_cathode += rhs.comp_.O2_cathode;
	      comp_.CO += rhs.comp_.CO;
	      comp_.CO2 += rhs.comp_.CO2;
	      comp_.CH4 += rhs.comp_.CH4;
	      comp_.N2_cathode += rhs.comp_.N2_cathode;
	      comp_.N2_anode += rhs.comp_.N2_anode;
	      comp_.O2_anode += rhs.comp_.O2_anode;
	      comp_.Air += rhs.comp_.Air;
	      comp_.H2O += rhs.comp_.H2O;
	    }
	  else
	    {
	      gas local(rhs);
	      if (mode_ == mol)
		{
		  local.to_mol();
		}
	      else
		{
		  local.to_L();
		}
	      comp_.H2 += local.comp_.H2;
	      comp_.O2_cathode += local.comp_.O2_cathode;
	      comp_.CO += local.comp_.CO;
	      comp_.CO2 += local.comp_.CO2;
	      comp_.CH4 += local.comp_.CH4;
	      comp_.N2_cathode += local.comp_.N2_cathode;
	      comp_.N2_anode += local.comp_.N2_anode;
	      comp_.O2_anode += local.comp_.O2_anode;
	      comp_.Air += local.comp_.Air;
	      comp_.H2O += local.comp_.H2O;
	    }
	} 
      else
	{
	  throw std::domain_error("Gasses can not be added unless temperature, mode and pressure are equal!");
	}
    }
  else
    {
      gas local(rhs);
      comp_.H2 += local.comp_.H2;
      comp_.O2_cathode += local.comp_.O2_cathode;
      comp_.CO += local.comp_.CO;
      comp_.CO2 += local.comp_.CO2;
      comp_.CH4 += local.comp_.CH4;
      comp_.N2_cathode += local.comp_.N2_cathode;
      comp_.N2_anode += local.comp_.N2_anode;
      comp_.O2_anode += local.comp_.O2_anode;
      comp_.Air += local.comp_.Air;
      comp_.H2O += local.comp_.H2O;
    }
  calc_pres();      
  return *this;	
}



// destructor
gas::~gas()
{
	
}
