// ==============================================================
// File Name    : Gmix.java
// Author       : Dr. Turhan Coban
// EGE University, School of engineering
// Department of Mechanical Engineering, bornova, izmir, TURKEY
// email        : Turhan.Coban@ege.edu.tr
// Description  : This file contains class gmix which  calculates
// thermophysical properties of mixture of perfect gases.
//               following properties can be calculated
//               T()     : Temperature degree K
//               h(T)    : enthalpy  KJ/kmol
//               hf      : formation enthalpy KJ/kg
//               ht(T)   : total enthalpy KJ/kg (h+hf)
//               M       : molar mass kg/kmol
//               HT(T)   : total enthalpy KJ : M*ht(T)
//               P()     : presure bar
//               s(T,P)  : entropy KJ/kmol K
//               Cp(T)   : specific heat at constant pressure KJ/kmol K
//               Cv(T)   : specific heat at constant volume KJ/kg K
//               gamma(T): adiabatic constant Cp/Cv
//               c(T)    : speed of sound m/s
//               u(T)    : Internal energy KJ/kmol
//               vis(T)  : viscosity
//               k(T)    : thermal conductivity KW/kg K
// DATA FILE DEFINATION
// gas mixture definations are given the data file "Gmix.txt"
// if gas mixture data is not given in the Gmix.txt user can be add
// his own data to the file which has the following format
//------------------
// gmixName
// ngas
// gname_0 N_0
// .........
// gname_ngas-1 N_ngas-1
//-------------------
// and defination : gmix a(gmixName); will defined this gas mixture
// the same mixture can be defined directly in the main program as :
// -------------------
// Gas a_0=new Gas("a_0");
//.......
// Gas a_ngas=new Gas("a_ngas);
// Gmix a=new Gmix;
// a=N_0*a_0+...+N_ngas*a_ngas;
// -------------------
//============================================================
//  VARIABLE IDENTIFICATION
// all the variables that type is not defined is a double variable
// PUBLIC  VARIABLES :
// gasName  : String class variable of gas mixture name
// ngas     : int variable, number of simple gasses
// N   : total molar mass of the gas mixture
// gasList  :gas class vector variables
// All the other variables defined for class gas is also valid for gmix
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;

// ==============================================================
   class Gmix extends absfluid{
// this class calculates perfect gas thermodynamic
// properties when the perfect gas constitutes of
// several single gases
        boolean mole=true;
        boolean SI=true;
        public int ngas;  // number of simple gasses inside of the gas mixture
        String gasName;
        public double M;  // molar mass of atom kg/kmol
        public double h0; // enthalpy at T=298 K
        public double hf; // enthalpy of formation
        public double sf; // entropy of formation    kJ/kmol K
        public double N;  // moles of gas kmol
        int ierror;
        int natom;          //number of unique atoms in the atom list
        Gas  gasList[];     //list of the component gasses
        Atom atomList[];    //list of component atoms
        File gmixFile;      // File name and directory
        BufferedReader cfin;
        // construction methods :
//========definations of class gmix =============================
//constructor functions
	public Gmix(String name) throws IOException
	{
        // class complex gas construction function
        // this function reads the initial gases in
	// the mixture and their molar weight from
        // the file Gmix.txt and construct mixed gas
    try{
      //cfin=new BufferedReader(new FileReader("data"+java.io.File.separator+"Gmix.txt"));
      cfin=new BufferedReader(new FileReader("Gmix.txt"));
	int ierror=1;
        int i,j;
        N=0;
      	M=0;
        hf=0;
        natom=0;
	try{
	while(cfin!=null)
	{
	gasName=Text.readString(cfin);
	if(gasName.equals(name)) { ierror=0; break;}
    } //end of while
        }  catch(EOFException e_eof)
     {
     System.out.println("error required gas mixture "+name+" is not found");
     cfin.close();return;
     }
     //cfin>>ngas;
     ngas=Text.readInt(cfin);
        gasList=new Gas[ngas];
	    //ierror=0;
        String pgasName;
        double ppercent;
        Gas tempgas;
	for(i=0;i<ngas;i++)
        {
        pgasName=Text.readString(cfin);
        ppercent=Text.readDouble(cfin);
        //cfin>>pgasName>>ppercent;
        tempgas=new Gas(pgasName,ppercent);
        ierror=tempgas.ierror;
        {
        if(ierror!=1)
          {
	      try{
             gasList[i]=new Gas(tempgas);
             gasList[i].mole=true; 
             } catch(IOException ioe) {System.out.println("IOException");}
	           N+=tempgas.N;
	           M+=tempgas.N*tempgas.M;
	      hf+=tempgas.N*tempgas.hf;
	      }
        else
          {
	      System.out.println("gas is not found in the list");
          System.out.println("this gas is not added to the list");
	      i--;
          ngas--;
          }
      }
      }
      M=M/N;
      hf=hf/N;
      arrange_atoms();
   } catch(FileNotFoundException fnfe) {System.out.println("File not found");}
   base("mole"); 
   }
// ==============================================================

public String readGmixNames() throws IOException
{   
    String temp=new String("");
    String pgasName;
    double ppercent;
    try{
      //cfin=new BufferedReader(new FileReader("data"+java.io.File.separator+"Gmix.txt"));
      cfin=new BufferedReader(new FileReader("Gmix.txt"));
               try {
               while(cfin!=null)
	       {
	       temp=temp+Text.readString(cfin)+ " ";
               ngas=Text.readInt(cfin);
                 for(int i=0;i<ngas;i++)
                 {
                 pgasName=Text.readString(cfin);
                 ppercent=Text.readDouble(cfin);
                 } //end of while
               }
               }  catch(EOFException e_eof)  {cfin.close();}
       }
       catch(FileNotFoundException fnfe) {System.out.println("File Gmix.txt not found");}
    return temp;
}

// ==============================================================

public void arrange_atoms()
{
int i,j;
      for(i=0;i<ngas;i++)
      {
	     for(j=0;j<gasList[i].natom;j++)
	     {
             add_atom(i,j);
             }
      }
}

public int  add_atom(int i,int j)
{
int k;
//Atom tempAtom=new Atom(gasList[i].atomList[j].symbol,gasList[i].atomList[j].N*gasList[i].N/N);
for(k=0;k<natom;k++)
{
//String s0=gasList[i].gasName;
String s1=gasList[i].atomList[j].symbol;
String s2=atomList[k].symbol;
//System.out.println("natom ="+natom+"k = "+k+atomList[k].symbol+"s0="+s0+"s1="+s1+"s2="+s2);
if(s1.equals(s2))
  {
  atomList[k]=new Atom(atomList[k].symbol,atomList[k].N+gasList[i].atomList[j].N*gasList[i].N/N);
  return 1;
  }
}
Atom atomL[];
atomL=new Atom[natom+1];
for(k=0;k<natom;k++)
atomL[k]=new Atom(atomList[k]);
atomL[natom]=new Atom(gasList[i].atomList[j].symbol,gasList[i].atomList[j].N*gasList[i].N/N);
atomList=atomL;
natom+=1;
return 2;
}

//===============================================================
   public Gmix() throws IOException
   {
   //empty construction function
   N=0;
   M=0;
   String pgasname="\0";
   ngas=0;
   base("mole");
   }
// ==============================================================
	public Gmix(Gmix g1) throws IOException
	{
	gasName=g1.gasName;
	N=g1.N;
	M=g1.M;
        hf=g1.hf;
	ngas=g1.ngas;
        natom=g1.natom;
	gasList=new Gas[ngas];
	for(int i=0;i<ngas;i++) gasList[i]=new Gas(g1.gasList[i]);
        for(int i=0;i<natom;i++) atomList[i]=new Atom(g1.atomList[i]);
    base("mole");    
    }
// ==============================================================
    public Gmix(Gas g1[])
	{
        N=0;
      	M=0;
        hf=0;
        natom=0;
        ngas=g1.length;
        gasList=new Gas[ngas];
        String pgasName;
        double ppercent;
	    for(int i=0;i<ngas;i++)
        {    gasList[i]=g1[i];
	         N+=gasList[i].N;
	         M+=gasList[i].N*gasList[i].M;
	         hf+=gasList[i].N*gasList[i].hf;
	     }
      M=M/N;
      hf=hf/N;
      arrange_atoms();
      base("mole");
   }

// ==============================================================
    public void changeN(double newN) throws IOException
	{
	normalise();
	for(int i=0;i<ngas;i++)
	  { gasList[i].N*=newN; }
          N=newN;
	}

	public boolean base(String s)
    {
    if(s.equals("mole")) {mole=true;for(int i=0;i<ngas;i++){ gasList[i].mole=true; }}
    else                 {mole=false;for(int i=0;i<ngas;i++){ gasList[i].mole=false;}}
    return mole;
    }

    public boolean unit(String s)
    {
    if(s.equals("SI")) {SI=true;for(int i=0;i<ngas;i++){ gasList[i].SI=true; }}
    else               {SI=false;for(int i=0;i<ngas;i++){ gasList[i].SI=false; }}
    return SI;
    }
// ==============================================================
	public void add(Gas g1) throws IOException
	{
	// this function adds a single gas to the mixture
        int gasflag=1;
        // if the gas exist in the list simply change N and M values
	for(int i=0;i<ngas;i++)
	{
	if(gasList[i].gasName.equals(g1.gasName))
	   {
	   gasflag=0;
           M=M*N+g1.M*g1.N;
	   gasList[i].N+=g1.N;
           N+=g1.N;
           M=M/N;
           }
	}
	if(gasflag!=0)
          {
	  Gas newGas[];
	  newGas=new Gas[ngas+1];
	  for(int i=0;i<ngas;i++)
	  {
	  newGas[i]=new Gas(gasList[i]);
	  }
	  ngas++;
	  double MT=M*N+g1.M*g1.N;
	  N+=g1.N;
	  M=MT/N;
	  newGas[ngas-1]=new Gas(g1);
	  gasList=newGas;
          }
        arrange_atoms();
        }
// ==============================================================
	public void remove(String name) throws IOException
	{
	// this function removes a  single gas
	// from the list
    int i,k;
	for(i=0;i<ngas;i++)
	  {
	    if(gasList[i].gasName.equals(name))
	      {
	      	Gas newGas[];
		    newGas=new Gas[ngas];
                M=0;
                N=0;
		for(k=0;k<i;k++)
		{ newGas[k]=new Gas(gasList[k]);
		  M+=newGas[k].M*newGas[k].N;
		  N+=newGas[k].N;
		}
		for( k=i;k<(ngas-1);k++)
		{
		  newGas[k]=new Gas(gasList[k+1]);
		  M+=newGas[k].M*newGas[k].N;
          N+=newGas[k].N;
		}
		M=M/N;
	      ngas--;
	    gasList=newGas;
	    break;
	      }
	  }
        arrange_atoms();
        // correct dynamic memory size
	}
// ==============================================================
	public void add(String name,double Nnew) throws IOException
	{
	// this function adds a single gas to the mixture
        Gas g1=new Gas(name,Nnew);
        int gasflag=1;
        // if the gas exist in the list simply change N and M values
	for(int i=0;i<ngas;i++)
	{
	if(gasList[i].gasName.equals(g1.gasName))
	   {
	   gasflag=0;
           M=M*N+g1.M*g1.N;
	   gasList[i].N+=g1.N;
           N+=g1.N;
           M=M/N;
           }
	}
	if(gasflag!=0)
          {
	  Gas newGas[];
	  newGas=new Gas[ngas+1];
	  for(int i=0;i<ngas;i++)
	  {
	  newGas[i]=new Gas(gasList[i]);
	  }
	  ngas++;
	  double MT=M*N+g1.M*g1.N;
	  N+=g1.N;
	  M=MT/N;
	  newGas[ngas-1]=new Gas(g1);
	  gasList=newGas;
          }
        arrange_atoms();
        }
// ==============================================================

	public void   simplify() throws IOException
	{
	// this function combines any  single gas
	// that repeated in the list
        double ngasold=ngas;
    int i,j,k;
	for(i=0;i<ngas;i++)
	  {
	  for(j=i+1;j<ngas;j++)
	    {
	    if(gasList[i].gasName.equals(gasList[j].gasName))
	      {
	      gasList[i].N+=gasList[j].N;
	      for(k=j;k<(ngas-1);k++)
	        { gasList[k]=new Gas(gasList[k+1]); }
	      ngas--;
	      }
	    }
	  }
        // correct dynamic memory size
	if(ngasold!=ngas)
        {
	Gas newGas[];
	newGas=new Gas[ngas];
	for(i=0;i<ngas;i++)
	  {
          newGas[i]=new Gas(gasList[i]);
	  }
	gasList=newGas;
	}
        }
// ==============================================================
public void  normalise() throws IOException
{
for(int i=0;i<ngas;i++)
  {
  gasList[i].N=gasList[i].N/N;
  }
N=1.0;
arrange_atoms();
}
// ==============================================================
public void changeMix(double Nmix[]) throws IOException
   {
   // this function changes
	// all the molar weights in the mixture
   N=0;
   M=0;
	for(int i=0;i<ngas;i++)
   {
   gasList[i].N=Nmix[i];
   N+=Nmix[i];
   M+=Nmix[i]*gasList[i].M;
   }
   M=M/N;
   arrange_atoms();
	}
// ==============================================================
  public double  vis(double T)
   {
   // dynamic viscosity of the mixture
   // note that viscosity of the mixture IS NOT the simple addition
   // of viscosity of component gasses
      double vmix=0;
   for(int i=0;i<ngas;i++)
     {
     T=T;
     double fij;
     double xj=0;
     double p1;
     double c1,c2,c3;
     for(int j=0;j<ngas;j++)
       {
       double vratio;
       double xi=gasList[i].M/gasList[j].M;
       if(gasList[j].vis(T)!=0)
         {
	     c1=gasList[i].vis(T)/gasList[j].vis(T);
	     vratio=Math.sqrt(c1);
	     }
       else
	     vratio=0;
	   c2=Math.pow(xi,0.25);
	   p1=(1+vratio/c2);
	   c3=8.0+8.0*xi;
	   fij=p1*p1 / Math.sqrt(c3);
       xj+=fij*gasList[j].N/N;
       }
     vmix+=gasList[i].N/N*gasList[i].vis(T)/xj;
     }
   return vmix;
   }
// ==============================================================
   public double  k(double T)
   {
   // thermal conductivity of the mixture
   // note that thermal conductivity  of the mixture IS NOT the
   // simple addition of the thermal conductivity  of component gasses
   double vmix=0;
   for(int i=0;i<ngas;i++)
     {
     T=T;
     double fij;
     double xj=0;
     double p1;
     double c1,c2,c3;
     for(int j=0;j<ngas;j++)
       {
       double vratio;
       double xi=gasList[i].M/gasList[j].M;
       if(gasList[j].k(T)!=0)
           {
	        c1=gasList[i].k(T)/gasList[j].k(T);
//           if(c1<0) System.out.println("negative c1 value ");
	        vratio=Math.sqrt(c1);
	       }
       else
	       vratio=0;
       c2=Math.pow(xi,0.25);
       p1=(1+vratio/c2);
       c3= 8.0+8.0*xi;
//       if(c2<0) System.out.println(" negative c2 value ");
       fij=p1*p1/Math.sqrt(c3);
       xj+=fij*gasList[j].N/N;
       }
     vmix+=gasList[i].N/N*gasList[i].k(T)/xj;
     }
   return vmix;
   }
// ==============================================================
   public double  Prandtl(double t)
   {
   // Prandtl number
   return Cp(t)*vis(t)/k(t)/M*1e3;
   }
// ==============================================================
   public double  h(double T)
   {
   //specific enthalpy of the mixture KJ/kmol
   double HH=0;
   for(int i=0;i<ngas;i++)
	{ HH+=gasList[i].h(T)*gasList[i].N; }
	return HH/N;
   }
   public double T(double h){	
		//Ridder Metodu ile lineer olmayan denklemlerin köklerinin bulunmas?
		//referans : Numerical Recipes in C, second edition, William H. Press, 
		//Saul A. Teukolsky, William T. Vetterling, Brian P. Flannery
		//cambridge university press	
		  double[][] x_bracket=new double[2][1]; 
		  x_bracket=T_bracket(h);	
		  double x1=x_bracket[0][0];
		  double x2=x_bracket[1][0];
		  //System.out.println("x1= "+x1+" x2= "+x2);
		  int MAXIT=50;
		    double xacc=1.0e-4;int j;
			double fl,fh,xl,xh,swap,dx,del,ff;
			double rtf=x1;
			fl=h(x1)-h;
			fh=h(x2)-h;
			//System.out.println("fl= "+fl+" fh= "+fh);
		    if (fl*fh > 0.0)System.out.println("Kök s?n?rlar? do?ru olarak seçilmemi? \n sonuç hatal? olabilir"); 
			if (fl < 0.0) {
				xl=x1;
				xh=x2;
			} else {
				xl=x2;
				xh=x1;
				swap=fl;
				fl=fh;
				fh=swap;
			}
			//System.out.println("xl= "+xl+" xh= "+xh);
			//System.out.println("fl= "+fl+" fh= "+fh);
			dx=xh-xl;
			for (j=1;j<=MAXIT;j++) {
				rtf=xl+dx*fl/(fl-fh);
				ff=h(rtf)-h;
				if (ff < 0.0) {
					del=xl-rtf;
					xl=rtf;
					fl=ff;
				} else {
					del=xh-rtf;
					xh=rtf;
					fh=ff;
				}
				//System.out.println("rtf= "+rtf);
				dx=xh-xl;
				//System.out.println("xl= "+xl+" xh= "+xh);
			//System.out.println("fl= "+fl+" fh= "+fh);
				if (Math.abs(del) < xacc || ff == 0.0) return rtf;
			}
			System.out.println("Uyarı maximum iterasyon say?s? a??ld? \n"+
		   " çözüm geçerli olmıyabilir");			
          return rtf; 
   }
   public double[][]  T_bracket(double h){
		// koklerin yer aldığı alt bölgeleri saptar
		// n : verilen bölgeyi böldü?ümüz alt bölge say?s?
		// x1,x2 : sınır de?erleri
		// nbb = aranan bölgedeki köksay?s?	
			int n=10;
			int nbb=1; 
			int nb;			
			int i;
			double x,fp,fc,dx;
			double x1=273.15;
			double x2=3000;
			double xb[][]=new double[2][nbb];
			nb=0;
			dx=(x2-x1)/n;
			x=x1;
			//System.out.println("===========================bracket basladi===================================");
			fp=h(x1)-h;
			//System.out.println("x1= "+x1+" fp= "+fp);
			for (i=1;i<=n;i++) 
			{
				x+=dx;
				fc=h(x)-h;
				//System.out.println("x= "+x+" fc= "+fc);
				// e?er kök olan bölge bulunduysa.....
				if (fc*fp < 0.0 || fp==0) {
					xb[0][nb]=x-dx;
					xb[1][nb]=x;
					nb++;
				}
				fp=fc;
				if (nbb == nb){
					//System.out.println("===========================bracket bitti===================================");
					 return xb;				 	 
				 }
			}	
		if( nb == 0)
		System.out.println("arama tamamland? kök olan bölge bulunamad?");			
		else if(nb<nbb){
			System.out.println("arama tamamland? sadece "+nb+" adet kök bulundu \n"+
		    "siz "+nbb+" adet kök için arama yapt?rd?n?z");			
		   double xc[][]=new double[2][nb];
		   for (i=0;i<nb;i++) {xc[0][i]=xb[0][i];xc[1][i]=xb[1][i];}
		   System.out.println("===========================bracket bitti===================================");
		   return xc;
		  }
		return xb;	   
   }
// ==============================================================
   public double  ht(double T)
   {
   //specific  enthalpy of the mixture ht=h+hf
   // hf : formation enthalpy
   double HH=0;
   for(int i=0;i<ngas;i++)
	{ HH+=gasList[i].ht(T)*gasList[i].N; }
   return HH/N;
   }
// ==============================================================
   public double  H(double t)
   {
   //total enthalpy of the mixture KJ
   return h(t)*N;
   }
// ==============================================================
   public double  HT(double t)
   //total enthalpy of the mixture HT=N*(h+hf)  KJ
   {
   return ht(t)*N;
   }
// ==============================================================
   public double  u(double T)
   {
   // specific internal energy of the mixture  KJ/kmol
   double UU=0;
   for(int i=0;i<ngas;i++)
	{ UU+=gasList[i].u(T)*gasList[i].N; }
   return UU/N;
   }
//===================================================================
public double g(double T,double P)
{
  return h(T)-T*s(T,P);
}

public double gt(double T,double P)
{
  return h(T)+hf-T*s(T,P);
}

public double gt(double T)
{
  double Pref;
  if(!SI) {Pref=14.503684;}
  else {Pref=1.0;}
  return h(T)+hf-T*s(T,Pref);
}


public double g(double T)
{
  double Pref;
  if(!SI) {Pref=14.503684;}
  else {Pref=1.0;}
  return h(T)-T*s(T,Pref);
}

public double G(double T,double P)
{
 return g(T,P)*N;
}

public double G(double T)
{
 return g(T)*N;
}

public double GT(double T)
{
 return gt(T)*N;
}

public double GT(double T,double P)
{
 return gt(T,P)*N;
}
// ==============================================================
   public double  Cp(double T)
   {
   // Specific energy at constant pressure  KJ/kmol K
   double C=0;
	for(int i=0;i<ngas;i++)
	{ C+=gasList[i].Cp(T)*gasList[i].N; }
   return C/N;
   }
// ==============================================================
   public double  Cv(double T)
   //Specific energy at constant volume  KJ/kmol K
   {
   double C=0;
   for(int i=0;i<ngas;i++)
	{ C+=gasList[i].Cv(T)*gasList[i].N; }
   return C/N;
   }
// ==============================================================
   public double  gamma(double T)
   {
   //adiabatic constant
   return Cp(T)/Cv(T);
   }
// ==============================================================
   public double  c(double T)
   //speed of sound m/s
   {
   return Math.sqrt(8314.5/M*T*gamma(T));
   }
// ==============================================================
   public double  s(double T, double P)
   {
   //specific entropy KJ/kmol K
   double SS=0;
   for(int i=0;i<ngas;i++)
	{
	SS+=gasList[i].s(T,P)*gasList[i].N;
	}
   return SS/N;
	}

   public double  s(double T)
   {
   //specific entropy KJ/kmol K
   double P=1.0;
   double SS=0;
   double s1,s2,s3,s4;
   for(int i=0;i<ngas;i++)
	{
	s1=gasList[i].s(T);
	s2=gasList[i].N;
	SS+=s1*s2;
	//System.out.println("T0"+T+"s1="+s1+"s2="+s2+"N="+N+"SS="+SS);
	}
   return SS/N;
	}
public double pr(double T)
{
double Tref, Rref;
  if(!SI) {Tref=491.67;Rref=1.986;}
  else {Tref=273.15;Rref=8.3145;}
  if(!mole) Rref/=M;
  double s1=s(T);
  double s2=s(Tref);
  double s3=Math.exp((s1-s2)/Rref);
  System.out.println("s1="+s1+"s2="+s2+"s3="+s3);
  return Math.exp((s(T)-s(Tref))/Rref);
}

public double vr(double T)
{
  double Rref;
  if(!SI) {Rref=1.986;}
  else {Rref=8.3145;}
  return (Rref/M)*T/pr(T)*10;
}

// ==============================================================
   public double  v(double T, double P)
   {
   double VV=0;
   for(int i=0;i<ngas;i++)
	{ VV+=gasList[i].v(T,P)*gasList[i].N; }
   return VV/N;
   }
// ==============================================================
public double  T( char name,double y0,double p)
{
double t=300;
if(name=='v') {t= p*1e5*y0/8.314e3;}
else
  {
  double dt;
  int nmax=400;
  double tolerance=1.0e-8;
  for(int i=0;i<nmax;i++)
    {
    if     (name=='h') dt=-( h(t)   - y0 ) /Cp(t);
    else if(name=='u') dt=-( u(t)   - y0 ) /Cv(t);
    else if(name=='s') dt=-( s(t,p) - y0 ) /(Cp(t)/t);
	 else { System.out.println("wrong name defined please try h,u,s ot v"); break;}
    t+=dt;
    if(Math.abs(dt)<tolerance) break;
    }
  }
return t;
}
// ==============================================================
public double  P( char name,double y0,double t1)
{
if(name=='v')       return 8.314e3*t1/y0*1e-5;
else if (name=='s') return Math.exp((s(t1,1.0)-y0)/8.314);
else { System.out.println("wrong name defined please try s or v"); return 1.0;}
}
// ==============================================================
public void  multiplyassign(double Nx)
{
	for(int i=0;i<ngas;i++)
	  { gasList[i].N*=Nx; }
	N*=Nx;
}
// ==============================================================
public void addassign(Gas g1) throws IOException
{
	// this function adds a single gas to the mixture
        int gasflag=1;
        // if the gas exist in the list simply change N and M values
	for(int i=0;i<ngas;i++)
	{
	if(gasList[i].gasName==g1.gasName)
	   {
	   gasflag=0;
           M=M*N+g1.M*g1.N;
	   gasList[i].N+=g1.N;
           N+=g1.N;
           M=M/N;
           }
	}
	if(gasflag!=0)
          {
	  Gas newGas[];
	  newGas=new Gas[ngas+1];
	  for(int i=0;i<ngas;i++)
	  {
	  newGas[i]=new Gas(gasList[i]);
	  }
	  ngas++;
	  double MT=M*N+g1.M*g1.N;
	  N+=g1.N;
	  M=MT/N;
	  newGas[ngas-1]=new Gas(g1);
	  gasList=newGas;
          }
}
// ==============================================================
public void addassign(Gmix right) throws IOException
{
 	// this function adds a gas mixture to the mixture
	for(int i=0;i<right.ngas;i++)
	{
        add(right.gasList[i]);
	}
}
// ==============================================================
public Gmix multiply( double Nx,Gmix right) throws IOException
{
Gmix g1=new Gmix(right);
g1.N*=Nx;
for(int i=0;i<g1.ngas;i++)
  {
  g1.gasList[i].N*=Nx;
  }
return g1;
}
// ==============================================================
// ==============================================================
public Gmix add(Gmix l,Gas r) throws IOException
{
Gmix g1=new Gmix(l);
Gas g2=new Gas(r);
g1.add(g2);
return  g1;
}
// ==============================================================
public Gmix  add(Gas l,Gmix r) throws IOException
{
Gmix g1=new Gmix(r);
Gas g2=new Gas(l);
g1.add(g2);
return g1;
}
// ==============================================================
public Gmix add(Gmix l,Gmix r) throws IOException
{
Gmix g1=new Gmix(l);
for(int i=0;i<r.ngas;i++)
	{
	g1.add(r.gasList[i]);
	}
return g1;
}
// ==============================================================
public void  assign(Gmix g1) throws IOException
{
	gasName=g1.gasName;
	N=g1.N;
	M=g1.M;
	ngas=g1.ngas;
	Gas newGas[];
    newGas=new Gas[ngas];
	for(int i=0;i<ngas;i++) newGas[i]=g1.gasList[i];
        gasList = newGas;
}
// ==============================================================
public void assign(Gas  g1) throws IOException
{
// a single gas is assigned to the mixture
   gasName=g1.gasName;
   N=g1.N;
   M=g1.M;
   ngas=1;
   gasList=new Gas[ngas];
   gasList[0]=new Gas(g1);
}

public String toString(String ch)
{
//return the c
String s="";
int i,j;
if(ch.equals("name"))
   s=s+gasName+"\n";
else if(ch.equals("formula"))
{
  for(i=0;i<ngas;i++)
  { s=s+" "+gasList[i].toString()+" "+gasList[i].N+"\n"; }
}
else if(ch.equals("composition"))
{
for(i=0;i<natom;i++)
  s=s+atomList[i].toString()+"\n";
}
return s;
}

public String[][] toString1(double v1, double v2)
{
  String s1[][]=new String[20][3];
   s1[0][0]="P, pressure                  ";
   s1[1][0]="T, temperature               ";
   s1[2][0]="v, specific volume           ";
   s1[3][0]="   density                   ";
   s1[4][0]="h, enthalpy                  ";
   s1[5][0]="u, internal energy           ";
   s1[6][0]="s, entropy                   ";
   s1[7][0]="g, qibbs free energy         ";
   s1[8][0]="ht,chemical entropy          ";
   s1[9][0]="gt,chemical gibbs f.e.       ";
   s1[10][0]="Cp, specific heat at const P ";
   s1[11][0]="Cv, specific heat at const v";
   s1[12][0]="Cp/Cv, adiabatic constant   ";
   s1[13][0]="c, speed of sound           ";
   s1[14][0]="viscosity                   ";
   s1[15][0]="thermal conductivity        ";
   s1[16][0]="M, molecular weight         ";
   s1[17][0]="Prandtl number              ";
   s1[18][0]="Pr, reduced pressure        ";
   s1[19][0]="vr, reduced volume          ";

   if(SI && !mole)
   {
   s1[0][2]=" bars          ";
   s1[1][2]=" deg K         ";
   s1[2][2]=" m^3/kg        ";
   s1[3][2]=" kg/m^3        ";
   s1[4][2]=" KJ/kg         ";
   s1[5][2]=" KJ/kg         ";
   s1[6][2]=" KJ/kg K       ";
   s1[7][2]=" KJ/kg         ";
   s1[8][2]=" KJ/kg         ";
   s1[9][2]=" KJ/kg         ";
   s1[10][2]=" KJ/kg K        ";
   s1[11][2]=" KJ/kg K       ";
   s1[12][2]="               ";
   s1[13][2]=" m/s           ";
   s1[14][2]=" Ns/m^2        ";
   s1[15][2]=" W/m K         ";
   s1[16][2]=" kg/kmol       ";
   s1[17][2]="               ";
   s1[18][2]="               ";
   s1[19][2]="               ";
   }
   else if(SI && mole)
   {
   s1[0][2]=" bars          ";
   s1[1][2]=" deg K         ";
   s1[2][2]=" m^3/kmole     ";
   s1[3][2]=" kmole/m^3     ";
   s1[4][2]=" KJ/kmole      ";
   s1[5][2]=" KJ/kmole      ";
   s1[6][2]=" KJ/kmole K    ";
   s1[7][2]=" KJ/kmole      ";
   s1[8][2]=" KJ/kmole      ";
   s1[9][2]=" KJ/kmole      ";
   s1[10][2]=" KJ/kmole K    ";
   s1[11][2]=" KJ/kmole K   ";
   s1[12][2]="               ";
   s1[13][2]=" m/s           ";
   s1[14][2]=" Ns/m^2        ";
   s1[15][2]=" W/m K         ";
   s1[16][2]=" kg/kmol       ";
   s1[17][2]="               ";
   s1[18][2]="               ";
   s1[19][2]="               ";
   }
   else if(!SI && mole)
   {
   s1[0][2]=" lbf/in^2, psia  ";
   s1[1][2]=" deg R           ";
   s1[2][2]=" ft^3/lbmole     ";
   s1[3][2]=" lbmole/ft^3     ";
   s1[4][2]=" BTU/lbmole      ";
   s1[5][2]=" BTU/lbmole      ";
   s1[6][2]=" BTU/lbmole K    ";
   s1[7][2]=" BTU/lbmole      ";
   s1[8][2]=" BTU/lbmole      ";
   s1[9][2]=" BTU/lbmole      ";
   s1[10][2]=" BTU/lbmole K   ";
   s1[11][2]=" BTU/lbmole K   ";
   s1[12][2]="                ";
   s1[13][2]=" ft/s           ";
   s1[14][2]=" lbm/(ft.s)     ";
   s1[15][2]=" BTU/(hr ft R)  ";
   s1[16][2]=" lbm/lbmole     ";
   s1[17][2]="                ";
   s1[18][2]="                ";
   s1[19][2]="                ";
   }
   else if(!SI && !mole)
   {
   s1[0][2]=" lbf/in^2, psia  ";
   s1[1][2]=" deg R           ";
   s1[2][2]=" ft^3/lbm     ";
   s1[3][2]=" ft^3/lbm     ";
   s1[4][2]=" BTU/lbm      ";
   s1[5][2]=" BTU/lbm      ";
   s1[6][2]=" BTU/lbm K    ";
   s1[7][2]=" BTU/lbm      ";
   s1[8][2]=" BTU/lbm      ";
   s1[9][2]=" BTU/lbm      ";
   s1[10][2]=" BTU/lbm K    ";
   s1[11][2]=" BTU/lbm K   ";
   s1[12][2]="                ";
   s1[13][2]=" ft/s           ";
   s1[14][2]=" lbm/(ft.s)     ";
   s1[15][2]=" BTU/(hr ft R)  ";
   s1[16][2]=" lbm/lbmole     ";
   s1[17][2]="                ";
   s1[18][2]="                ";
   s1[19][2]="                ";
   }
   double pp[]=property(v1,v2);
   for(int i=0;i<20;i++)
   {s1[i][1]=""+pp[i];}
return s1;
}

public double[] property(double t, double p)
{
double pp[]=new double[20];
pp[0]=p;
pp[1]=t;
pp[2]=v(t,p);
pp[3]=1.0/pp[2];
pp[4]=h(t);
pp[5]=u(t);
pp[6]=s(t,p);
pp[7]=g(t,p);
pp[8]=ht(t);
pp[9]=gt(t,p);
pp[10]=Cp(t);
pp[11]=Cv(t);
pp[12]=gamma(t);
pp[13]=c(t);
pp[14]=vis(t);
pp[15]=k(t);
pp[16]=M;
pp[17]=Prandtl(t);
pp[18]=pr(t);
pp[19]=vr(t);
return pp;
}
/*
*Implemented methods from fluidInterface class
*/ 	
 	public static absfluid getInstance(String fluidName) throws java.io.IOException {	 	
	 	return new Gmix(fluidName);	
 	}
	public double h_TP(double T,double P) throws GException {
			return h(T);            
	}
	public double T(double h,double P) throws GException {
			return T(h);            
	}
	public double h_TV(double T,double V) throws GException {
			return h(T);            
	}
	public double x(double T,double V)throws GException{
			return 2;  
	}
	public double k(double T,double P) throws GException {
			return k(T);
	}
	public double vis(double T,double P) throws GException {
			return vis(T);       
	}
	public double ro(double T,double P)throws GException{					                             
            return 1/v(T,P); 
    }
    public double cp(double T,double P)throws GException{					                             
            return Cp(T);			
	}
	public double sigma(double T,double P) throws GException {
			return Double.NaN;
	}
	//===================================================================
//sıfırlamak istediğim fonksiyon
double fp(double Pri,double ti,double pi)
{ double a[]=property(ti,pi);
	return a[17]-Pri;
}

public double Ti(double Pri,double Pi)
{
double a=300.0;
double b=2500.0;
// brent metodu ile kök değerini bulur
double test;
double p=0;
double es,ea;
double f1,f2,f3,fp;
int maxit=500,iter=0;
double tol=1.0e-5;
es=0.001;
double x1=a;f1=fp(Pri,x1,Pi);
double x2=b;f2=fp(Pri,x2,Pi);
double x3=(x1+x2)/2.0;f3=fp(Pri,x3,Pi);
if(f1==0) return x1;
else if(f2==0) return x2;
else if(f3==0) return x3; 
//if(f1*f2>0) System.out.println("verilen bölgede kök yok");
p=-(f2*f3*x1*(f2-f3)+f3*f1*x2*(f3-f1)+f1*f2*x3*(f1-f2))/((f1-f2)*(f2-f3)*(f3-f1));
fp=fp(Pri,p,Pi);
//System.out.println("p="+p+"fp="+fp);  
ea=Math.abs(x3-p);
while((ea>es)&&(iter<maxit))
{	if(Math.abs(f3)<tol) return x3; 
    if((p<x1) && (p>x2)) 
    {p=(x1+x2)/2.0;    
     if(p>x3) {x1=x3;f1=f3;x3=p;f3=fp;}
     else if(p<x3) {x2=x3;f2=f3;x3=p;f3=fp;}
    }
    else
    {        
    if(p>x3) {x1=x3;f1=f3;x3=p;f3=fp;}
    else if(p<x3) {x2=x3;f2=f3;x3=p;f3=fp;}
    p=-(f2*f3*x1*(f2-f3)+f3*f1*x2*(f3-f1)+f1*f2*x3*(f1-f2))/((f1-f2)*(f2-f3)*(f3-f1));
    fp=fp(Pri,p,Pi); 
    ea=Math.abs(x3-p);
    }
    iter++;
} 
if(iter>=maxit) JOptionPane.showMessageDialog(null,"Uyarı maximum iterasyon sayısı aşıldı \n"+
   " çözüm geçerli olmıyabilir","MAKSİMUM ITERASYON SAYISI UYARISI",JOptionPane.WARNING_MESSAGE); 
return p;
}

}//end of class
