// ==============================================================
// File Name    : LeeKeslerMix.java
// Author       : Dr. Turhan Coban
// TUBÝTAK Marmara Research Center
// Energy Systems and Environmental Research Institute
// email : Turhan.Coban@posta.mam.gov.tr
// Description  : This file contains class LeeKeslerMix which  calculates
// thermophysical properties of mixture of real fluids.

// DATA FILE DEFINATION
// gas mixture definations are given the data file "RealGasMix.txt"
// if gas mixture data is not given in the RealGasMix.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
//-------------------
//============================================================
//  VARIABLE IDENTIFICATION

import java.io.*;
import java.util.*;
//import Text;
//import LeeKesler;
//import Matrix;

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

class LeeKeslerMix extends LeeKesler
{
// this class calculates real fluid thermodynamic
// properties when the real fluid constitutes of
// several single gases
        public int ngas;          // number of simple fluids inside of the fluid mixture
        LeeKesler  gasList[];     //list of the component real fluids
        BufferedReader cfin;
        double Tb_start,Tb_end;
//=======================================================================
// constructor methods :
//========definations of class LeeKeslerMix =============================

	public LeeKeslerMix(String name) throws IOException
	{
  // class mixed real fluid construction function
  // this function reads the initial real fluids
	// the mixture and their molar weight from
  // the file RealGasMix.txt and construct mixed gas
        int i,j;
        try{
        cfin=new BufferedReader(new FileReader("RealGasMix.txt"));
	      int ierror=1;

	      N=0;
	      M=0;
        natom=0;
        ngas=0;
      	try{
      	   while(cfin!=null)
	         {
      	      Name=Text.readString(cfin);
       	      if(Name.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;
              }
           ngas=Text.readInt(cfin);
           gasList=new LeeKesler[ngas];
           String pgasName;
           double ppercent;
      	   for(i=0;i<ngas;i++)
           {
              try {
              pgasName=Text.readString(cfin);
              ppercent=Text.readDouble(cfin);
              gasList[i]=new LeeKesler(pgasName,ppercent);
              N+=gasList[i].N;
              M+=gasList[i].N*gasList[i].M;
                 }  catch(IOException ioe)
                 { System.out.println("IOException");
                   ierror=gasList[i].ierror;
                  } //end of for block
           }
      M=M/N;
      arrange_atoms();
      double Vcij[][]=new double[ngas][ngas];
      double Tcij[][]=new double[ngas][ngas];
      double kij;
      for(i=0;i<ngas;i++)
      {
        for(j=0;j<ngas;j++)
        {
         if(i==j)
         {
         Vcij[i][j]=gasList[i].Vc;
         Tcij[i][j]=gasList[i].Tc;
          }
         else
         {
         Vcij[i][j]=Math.pow((Math.pow(gasList[i].Vc,(1.0/3.0))+Math.pow(gasList[j].Vc,(1.0/3.0))),3.0)/8.0;
         kij=Math.sqrt(gasList[i].Vc*gasList[j].Vc)/Vcij[i][j];
         Tcij[i][j]=kij*Math.sqrt(gasList[i].Tc*gasList[j].Tc);
         }
         //System.out.println("kij "+kij+"i="+i+"j="+j+"Vcij="+Vcij[i][j]+"Tcij="+Tcij[i][j]);
        }
        //System.out.println(" ");
      }
      Tc=0;
      Vc=0;
      Omega=0;
      Pc=0;
      Tb=0;
      Tfp=0;
      for(i=0;i<ngas;i++)
      {
        for(j=0;j<ngas;j++)
        {
         Tc+=gasList[i].N*gasList[j].N/(N*N)*Math.pow(Vcij[i][j],(1.0/4.0))*Tcij[i][j];
         Vc+=gasList[i].N*gasList[j].N/(N*N)*Vcij[i][j];
         }
      }
      DELHF=0;
      DELGF=0;
      DELS0=0;
      LDEN=0;
      TDEN=0;
      for(i=0;i<ngas;i++)
      {
      Omega+=gasList[i].N/N*gasList[i].Omega;
      Tb+=gasList[i].N/N*gasList[i].Tb;
      Tfp+=gasList[i].N/N*gasList[i].Tfp;
      DELHF+=gasList[i].N/N*gasList[i].DELHF;
      DELGF+=gasList[i].N/N*gasList[i].DELGF;
      DELS0+=gasList[i].N/N*gasList[i].DELS0;
      LDEN+=gasList[i].N/N*gasList[i].LDEN;
      TDEN+=gasList[i].N/N*gasList[i].TDEN;
      }
      Tc/=Math.pow(Vc,(1.0/4.0));
      Pc=(0.2905-0.085*Omega)*R*Tc/Vc*1e-2;
      Zc=(Pc*1e5)*(Vc*1e-3)/(R*Tc);
      //System.out.println("Tc = "+Tc+"Pc = "+Pc+"Vc = "+Vc+"Omega = "+Omega+"Zc="+Zc);
      name=toString("name");
      Formula=toString("composition");
       } catch(FileNotFoundException fnfe) {System.out.println("File not found");}
      MolWt=M;
      Dipm=0;
      CPC[0]=CPC[1]=CPC[2]=CPC[3]=0;
      VPC[0]=VPC[1]=VPC[2]=VPC[3]=0;
      VPEq=4;
      // sort data
      for(int top=gasList.length-1;top>0;top--)
      {
        for(i=0;i<top;i++)
        {
        if(gasList[i+1].Tb < gasList[i].Tb)
           swap(i+1,i);
        }
      }
      Tb_start=gasList[0].Tb;
      Tb_end=gasList[ngas-1].Tb;
}

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

public void swap(int i,int j)
{
// this method is used the swap two LeeKesler fluid with each other
LeeKesler temp=new LeeKesler(gasList[i]);
gasList[i]=new LeeKesler(gasList[j]);
gasList[j]=new LeeKesler(temp);
}

public void arrange_atoms() throws IOException
{
   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) throws IOException
{

int k;
for(k=0;k<natom;k++)
{
if(gasList[i].atomList[j].symbol.equals(atomList[k].symbol))
  {
  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 double Tb_max(double P)
{
//maximum boiling point
Tb=0;
for(int k=0;k<ngas;k++)
{
  double Tbx=gasList[k].T_P_GT_SV(P);
  System.out.println("k="+gasList[k].toString()+" "+Tbx);
  if(Tbx>Tb) Tb=Tbx;
}
return Tb;
}

public double Tb_min(double P)
{
/*
	//minimum boiling point
Tb=3000;
for(int k=0;k<ngas;k++)
{
  double Tbx=gasList[k].T_P_SV(P);
  if(Tbx<Tb) Tb=Tbx;
}
return Tb;
*/
return gasList[0].T_P_SV(P);
}

public double dH_P_TS_SVL1(double P)
{
double dh=0;
for(int k=0;k<ngas;k++)
{
  dh+=gasList[k].N*gasList[k].dH_P_TS_SVL(P);
}
dh/=N;
return dh;
}

public double dH_TP_SV_V1(double P)
{
double dh=0;
double Tmax=Tb_max(P);
double Tboil;
for(int k=0;k<ngas;k++)
{
  Tboil=gasList[k].T_P_LK_SV(P);
  //System.out.println(gasList[k].toString()+" "+Tboil);
  dh+=gasList[k].N*
  (
  gasList[k].h_TP_LK_V(Tmax,P)-
  gasList[k].h_TP_LK_V(Tboil,P)
  );
}
dh/=N;
return dh;
}

public double dH_P_VE_SVL1(double P)
{
double dh=0;
double dhi;
for(int k=0;k<ngas;k++)
{
  dhi=gasList[k].dH_P_VE_SVL(P);
  System.out.println(gasList[k].toString()+" dh = "+dhi);
  dh+=gasList[k].N*dhi;
}
dh/=N;
return dh;
}

public double dH_P_WE_SVL1(double P)
{
double dh=0;
for(int k=0;k<ngas;k++)
{
  dh+=gasList[k].N*gasList[k].dH_P_WE_SVL(P);
}
dh/=N;
return dh;
}

public double dH_P_LK_SVL1(double P)
{
	// kaynama entalpisi
double dh=0;
for(int k=0;k<ngas;k++)
{
  dh+=gasList[k].N*gasList[k].dH_P_LK_SVL(P);
}
dh/=N;
return dh;
}

public double dH_P_GT_SVL1(double P)
{
double dh=0;
for(int k=0;k<ngas;k++)
{
  dh+=gasList[k].N*gasList[k].dH_P_GT_SVL(P);
}
dh/=N;
return dh;
}

public String toString(String ch)
{
String s="";
int i,j;
if(ch.equals("name"))
   s=s+Name+"\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 double h_T_IG_V(double T)
{
//enthalpy of ideal gas
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].h_T_IG_V(T);
  //System.out.println(gasList[i].toString()+" "+gasList[i].h_T_IG_V(T)+"h = "+h);
  }
  h/=N;
  return h;
}

public double dH_T_GT_SVL1(double T)
{
//
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].dH_T_GT_SVL(T);
  //System.out.println(gasList[i].toString()+" "+gasList[i].dh_T_GT_SVL(T)+"h = "+h);
  }
  h/=N;
  return h;
}

public double dH_T_LK_SVL1(double T)
{
//
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].dH_T_LK_SVL(T);
  //System.out.println(gasList[i].toString()+" "+gasList[i].dH_T_LK_SVL(T)+"h = "+h);
  }
  h/=N;
  return h;
}

public double dH_T_TS_SVL1(double T)
{
//enthalpy of ideal gas
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].dH_T_TS_SVL(T);
  //System.out.println(gasList[i].toString()+" "+gasList[i].dH_T_TS_SVL(T)+"h = "+h);
  }
  h/=N;
  return h;
}

public double dH_T_VE_SVL1(double T)
{
//enthalpy of ideal gas
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].dH_T_VE_SVL(T);
  //System.out.println(gasList[i].toString()+" "+gasList[i].dH_T_VE_SVL(T)+"h = "+h);
  }
  h/=N;
  return h;
}

public double dH_T_WE_SVL1(double T)
{
//enthalpy of ideal gas
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].dH_T_WE_SVL(T);
  //System.out.println(gasList[i].toString()+" "+gasList[i].dH_T_WE_SVL(T)+"h = "+h);
  }
  h/=N;
  return h;
}

public double Cp_T_IG_V(double T)
{
//ideal gas Cp
  double Cp=0;
  for(int i=0;i<ngas;i++)
  {
  Cp+=gasList[i].N*gasList[i].Cp_T_IG_V(T);
  //System.out.println(gasList[i].toString()+" "+gasList[i].N+" "+gasList[i].Cp_T_IG_V(T)+"Cp = "+Cp);
  }
  Cp/=N;
  return Cp;
}

public double Cp_TP_BR_L(double T, double P)
{
//liquid Cp
  double Cp=0;
  for(int i=0;i<ngas;i++)
  {
  Cp+=gasList[i].N*gasList[i].Cp_TP_BR_L(T,P);
  //System.out.println(gasList[i].toString()+" "+gasList[i].N+" "+gasList[i].Cp_T_IG_V(T)+"Cp = "+Cp);
  }
  Cp/=N;
  return Cp;
}

public double Cp_T_BR_SL(double T)
{
//saturated liquid Cp
  double Cp=0;
  for(int i=0;i<ngas;i++)
  {
  Cp+=gasList[i].N*gasList[i].Cp_T_BR_SL(T);
  //System.out.println(gasList[i].toString()+" "+gasList[i].N+" "+gasList[i].Cs_T_IG_V(T)+"Cp = "+Cp);
  }
  Cp/=N;
  return Cp;
}

public double h_T_BR_SL(double T)
{
//saturated vapor h
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].h_T_BR_SL(T);
  }
  h/=N;
  return h;
}

public double h_P_BR_SL(double P)
{
//saturated vapor h
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].h_P_BR_SL(P);
  }
  h/=N;
  return h;
}


public double dhsh_TP_V(double T, double P)
{
//superheated vapor h
  double h=0;
  for(int i=0;i<ngas;i++)
  {
  h+=gasList[i].N*gasList[i].dhsh_TP_V(T,P);
  }
  h/=N;
  return h;
}

public double[][] distilation(double P)
{
  //generates saturated liquid distilation list
  double Ni=0;
  double[][] x=new double[ngas][2];
  for(int i=0;i<ngas;i++)
  {
   Ni+=gasList[i].N;
   x[i][0]=Ni;
   x[i][1]=gasList[i].T_P_LK_SV(P);
  }
  return x;
}

public double[][] distilationGT(double P)
{
  //generates saturated liquid distilation list
  double Ni=0;
  double[][] x=new double[ngas][2];
  for(int i=0;i<ngas;i++)
  {
   Ni+=gasList[i].N;
   x[i][0]=Ni;
   x[i][1]=gasList[i].T_P_GT_SV(P);
  }
  return x;
}

}//end of class


