import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class chemicalReaction1
{String name[];
double N[][];
Gas1 g[];
int natom,ngas;
int nrt,npt;
String reacName;
double A[][];
double b0[];
double b1[];
Atom atomList[];
String atomnames[];
String atomsymbols[];
chemicalReaction1(String crname,String si[],double Ni[][]) 
{ reacName=crname;
  ngas=si.length;
name=new String[ngas];
N=new double[ngas][2];
g=new Gas1[ngas];
for(int i=0;i<ngas;i++)
{  name[i]=si[i];
   g[i]=new Gas1(name[i]);
}
for(int i=0;i<ngas;i++)
{N[i][0]=Ni[i][0];N[i][1]=Ni[i][1];}
     arrange_atoms();
     conservation();
}
chemicalReaction1(String name) throws IOException
{ File reacFile=new File("Reaction.txt");
  int ngas;
  String tempGasName="";
  try
     {    
     BufferedReader cfin=new BufferedReader(new FileReader(reacFile));
     int ierror=1;
     natom=0;
     try
       {
       while(cfin!=null)
         {
         reacName=Text.readString(cfin);
         if(reacName.equals(name)) {ierror=0;break;}
         }
       }
       catch(EOFException e_eof)
         {
         System.out.println("error required gas mixture "+name+" is not found");
         cfin.close();return;
         }
       ngas=Text.readInt(cfin);
       g=new Gas1[ngas];
       N=new double[ngas][2];
       nrt=0;
       npt=0;

       Double n1,n2;
       for(int i=0;i<ngas;i++)
         {
         tempGasName=Text.readString(cfin);
         N[i][0]=Text.readDouble(cfin);
         N[i][1]=Text.readDouble(cfin);
         nrt+=N[i][0];
         npt+=N[i][1];
         g[i]=new Gas1(tempGasName);
         }
       }
     catch(FileNotFoundException fnfe) {System.out.println("File Not Found");}
     name=tempGasName;
     arrange_atoms();   //end of constructor
     conservation();
}     
     public void arrange_atoms() 
     {
     // atomic structure of the reactants
     int i,j;
        for(i=0;i<ngas;i++)
        {for(j=0;j<g[i].natom;j++)
	     {add_atom(i,j);}
        }
     }

     public int  add_atom(int i,int j) 
     {
     //determine and order the atomic structure
     int k;
       for(k=0;k<natom;k++)
       {
       if(g[i].atomList[j].symbol.equals(atomList[k].symbol))
         {
         atomList[k]=new Atom(atomList[k].symbol,atomList[k].N+g[i].atomList[j].N*N[i][0]);
         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(g[i].atomList[j].symbol,g[i].atomList[j].N*N[i][0]);
     atomList=atomL;
     natom+=1;
     return 2;
     }
     public String toString()
     {
       // writes chemical reaction in chemistry norm
       String s="";
       for(int i=0;i<ngas;i++)
       {
       if(N[i][0]==1)
           { s+=g[i].toString(); }
       else if(N[i][0]!=0)
           { s+=N[i][0]+" "+g[i].toString(); }
       if(i!=(ngas-1) && N[i][0]!=0 ) s+=" + ";
       }
       if(s.endsWith(" + "))
         s=s.substring(0,s.length()-3);
       s+=" --> ";
       for(int i=0;i<ngas;i++)
       {
       if(N[i][1]==1)
           { s+=g[i].toString(); }
       else if(N[i][1]!=0)
           { s+=N[i][1]+" "+g[i].toString(); }
       if(i!=(ngas-1) && N[i][1]!=0 ) s+=" + ";
       }
       if(s.endsWith(" + "))
         s=s.substring(0,s.length()-3);
     return s;
     }
     public String toStringE()
     {
       // writes chemical reaction in chemistry equilibrium norm
       String s="";
       for(int i=0;i<ngas;i++)
       {
       if(N[i][0]==1)
           { s+=g[i].toString(); }
       else if(N[i][0]!=0)
           { s+=N[i][0]+" "+g[i].toString(); }
       if(i!=(ngas-1) && N[i][0]!=0 ) s+=" + ";
       }
       if(s.endsWith(" + "))
         s=s.substring(0,s.length()-3);
       s+=" "+'\u21C4'+" ";
       for(int i=0;i<ngas;i++)
       {
       if(N[i][1]==1)
           { s+=g[i].toString(); }
       else if(N[i][1]!=0)
           { s+=N[i][1]+" "+g[i].toString(); }
       if(i!=(ngas-1) && N[i][1]!=0 ) s+=" + ";
       }
       if(s.endsWith(" + "))
         s=s.substring(0,s.length()-3);
     return s;
     }
     public String toString(String ch)
     {
     //return the c
     String s="";
     int i,j;
     if(ch.equals("name"))
        s=s+reacName+"\n";
     else if(ch.equals("formula"))
        {
        s=toString();
        }
     else if(ch.equals("composition"))
        {
        for(i=0;i<natom;i++)
        s=s+atomList[i].toString()+" ";
        }
     return s;
     }     
     public double H(double TR,double TP)
     {
     // reaction enthalpy
      double HH=0;
      double h1,h2;
      for(int i=0;i<ngas;i++)
      {
       h1=g[i].ht(TP)*N[i][1];
       h2=g[i].ht(TR)*N[i][0];
       //System.out.println("h1="+h1+"h2="+h2);
	   HH+=h1;
       HH-=h2;
      }
      return HH;
     }
     public double S(double TR,double TP,double pt)
     {
     //reaction entropy
      double TP1,TR1,pt1;
      double s1,s2;
      TR1=TR;TP1=TP;pt1=pt;
      double SS=0;
      for(int i=0;i<ngas;i++)
      {
       if(N[i][1]!=0)
          SS+=g[i].si(TP1,N[i][1]/npt*pt1)*N[i][0];
       if(N[i][0]!=0)
          SS-=g[i].Si(TR1,N[i][0]/nrt*pt1)*N[i][1];
      }
        return SS;
     }
     public double S(double TR,double TP)
     {
     //reaction entropy
      double TP1,TR1,pt1,pt;
      pt=1.0;TR1=TR;TP1=TP;pt1=pt;
      return S(TR,TP,pt);
     }
     public double G(double TR,double TP,double pt)
     {
     // reaction gibbs energy
      double TP1,TR1,pt1;
      TR1=TR;TP1=TP;pt1=pt;
      double GG=0;
      for(int i=0;i<ngas;i++)
      {
       if(N[i][1]!=0)
          GG+=g[i].gt(TP1,N[i][1]/npt*pt1)*N[i][1];
       if(N[i][0]!=0)
          GG-=g[i].gt(TR1,N[i][0]/nrt*pt1)*N[i][0];
      }
        return GG;
     }
     
     public double G(double TR,double TP)
     { // reaction gibbs energy
       double TP1,TR1,pt1,pt;
       pt=1.0;TR1=TR;TP1=TP;pt1=pt;
       return G(TR,TP,pt);
     }
     
     public double G0(double TR,double TP)
     {
     // reaction gibbs energy
      double GG=0;
      double h1=0;
      for(int i=0;i<ngas;i++)
      {
       if(N[i][1]!=0)
          { h1=g[i].gt(TP)*N[i][1];GG+=h1;}
       if(N[i][0]!=0)
          { h1=g[i].gt(TR)*N[i][0];GG-=h1;}
      }
       return GG;
     }
     public double K(double TR,double TP)
     {
     // Equilibrium costant. Usually TR and TP will be in
     // the same temperature
     return Math.exp(G0(TR,TP)/(-8.3145*TP));
     }
     public double lnK(double TR,double TP)
     {
     // Equilibrium costant. Usually TR and TP will be in
     // the same temperature
     return G0(TR,TP)/(-8.3145*TP);
     }     
     public boolean conservation()
     {	    	 //Gives atomic mass balance of the chemical reaction
                 atomnames=new String[natom];
                 atomsymbols=new String[natom];
	             boolean bb=true;
                 int nn=ngas;
			     int nat=g[0].atomList[0].atom_name.length;
			     double B[][]=new double[nat][nn];
			     int nk=0;		
			     for(int i=0;i<nn;i++)
			     {
				    for(nk=0;nk<g[i].atomList.length;nk++){
					   B[g[i].atomList[nk].number-1][i]=g[i].atomList[nk].N;
					}
				 }
			     int natcount=0;
			     boolean zeroflag[]=new boolean[nat];
			     for(int j=0;j<nat;j++)
			     {  zeroflag[j]=false;
			        for(int i=0;i<nn;i++)
			        {if(B[j][i]!=0){zeroflag[j]=true;}};
			        if(zeroflag[j]) 
			        {atomnames[natcount]=g[0].atomList[0].atom_name[j];
			         atomsymbols[natcount]=g[0].atomList[0].atom_symbol[j];
			         natcount++;}
			     }
			     A=new double[natcount][nn];		
			     int k=0;
			     for(int j=0;j<nat;j++)
			      {if(zeroflag[j]){A[k]=B[j];k++;}}	
			     natom=A.length;
			     ngas=A[0].length;
			     b0=new double[natom];
			     for(int ii=0;ii<natom;ii++)
			     {
				   for(int ij=0;ij<ngas;ij++)
				   {
					  double carpim=A[ii][ij]*N[ij][0];	
					  b0[ii]+=carpim;		
				   }						
			     }
			      b1=new double[natom];
			     for(int ii=0;ii<natom;ii++)
			     {
				   for(int ij=0;ij<ngas;ij++)
				      {
					  double carpim=A[ii][ij]*N[ij][1];	
					  b1[ii]+=carpim;		
				      }						
			     }
			     for(int ii=0;ii<natom;ii++)
				 {
                    if(b0[ii]==b1[ii]) bb=bb&&true;
                    else		       bb=bb&&false;
				 }
				 return bb;				     
     }
     public  void equilibrium_print(double TR,double TP)
     { 
     JTextArea jta;
     JPanel jpan=new JPanel();
     jpan.setLayout(new BorderLayout());
     String s="Equilibrium Reaction name  : "+toString("name")+"\n";
     s+="Equilibrium  formula     : "+toStringE()+"\n";
     s+="Treactant = "+TR+" degree K\n";
     s+="Tproduct  = "+TP+ " degree K\n";
     s+="Equilibrium constant K = "+K(TR,TP)+"\n";
     s+="Equilibrium constant lnK = "+lnK(TR,TP)+"\n";
      s+="Equilibrium constant log10K = "+Math.log10(K(TR,TP))+"\n";
     s+="Reaction composition : "+toString("composition")+"\n";
     s+="Atom balance check   : "+conservation()+"\n";    
     s+="Atomic balance:";
     jta=new JTextArea(s);
     natom=A.length;
     ngas=A[0].length;
     String bb="Equilibrium Chemical Reaction";
     String baslik[]=new String[ngas+3];
     String s1[][]=new String[natom][ngas+3];
     int i,j;
     for(i=0;i<ngas;i++)
     {baslik[i+1]=g[i].gasName;}
     baslik[i+1]="b0(reactants)";
     baslik[i+2]="b1(products)";
     
     for(j=0;j<natom;j++)
     {s1[j][0]=atomsymbols[j];}
     for(j=0;j<natom;j++) 
      { for(i=0;i<ngas;i++) 
         {s1[j][i+1]=""+A[j][i];}
      }
      for(j=0;j<natom;j++) 
         {s1[j][i+1]=""+b0[j];
          s1[j][i+2]=""+b1[j];
         }
	 JTable jt;
	 int n=A.length;
	 int m=A[0].length;
	 genelModel gm=new genelModel(s1,baslik);
	 jt=new JTable(gm);
	  //JOptionPane.showMessageDialog(null,jt);
	  jpan.add(jta,BorderLayout.NORTH);
	  jpan.add(new JScrollPane(jt),BorderLayout.SOUTH);
     JFrame cerceve=new JFrame(bb);
     cerceve.addWindowListener(new BasicWindowMonitor());
     cerceve.getContentPane().add(new JScrollPane(jpan));
     cerceve.pack();
     cerceve.setVisible(true);
	 }
     public  void print(double TR,double TP)
     { 
     JTextArea jta;
     JPanel jpan=new JPanel();
     jpan.setLayout(new BorderLayout());
     String s="Reaction name  : "+toString("name")+"\n";
     s+="Reaction formula     : "+toString("formula")+"\n";
     s+="Reaction composition : "+toString("composition")+"\n";
     s+="Atom balance check   : "+conservation()+"\n";
     s+="Treactant = "+TR+" degree K\n";
     s+="Tproduct  = "+TP+ " degree K\n";
     double Taf=Taf(TR,298.0,2000.0);
     if(Taf>1999.0&&Taf<=2000.0 ) Taf=Taf(TR,298.0,3000.0);
     if(Taf>2999.9&&Taf<=3000.0) Taf=Taf(TR,298.0,4000.0);
     if(Taf>3999.9&&Taf<=4000.0) Taf=Taf(TR,298.0,5000.0);
     s+="Adiabatic flame temperature = "+Taf+"\n";
     double Q1=H(298.15,298.15);
     s+="Heating value = "+Q1+" kJ/kmol\n";
     double Q2=H(TR,TP);
     s+="Q = "+Q2+" kJ/kmol \n";
     s+="heating efficiency = "+Q2/Q1+"\n";
     s+="\n";
     s+="Atomic balance:";
     jta=new JTextArea(s);
     natom=A.length;
     ngas=A[0].length;
     String bb="Chemical Reaction";
     String baslik[]=new String[ngas+3];
     String s1[][]=new String[natom][ngas+3];
     int i,j;
     for(i=0;i<ngas;i++)
     {baslik[i+1]=g[i].gasName;}
     baslik[i+1]="b0(reactants)";
     baslik[i+2]="b1(products)";
     
     for(j=0;j<natom;j++)
     {s1[j][0]=atomsymbols[j];}
     for(j=0;j<natom;j++) 
      { for(i=0;i<ngas;i++) 
         {s1[j][i+1]=""+A[j][i];}
      }
      for(j=0;j<natom;j++) 
         {s1[j][i+1]=""+b0[j];
          s1[j][i+2]=""+b1[j];
         }
	 JTable jt;
	 int n=A.length;
	 int m=A[0].length;
	 genelModel gm=new genelModel(s1,baslik);
	 jt=new JTable(gm);
	  //JOptionPane.showMessageDialog(null,jt);
	  jpan.add(jta,BorderLayout.NORTH);
	  jpan.add(new JScrollPane(jt),BorderLayout.SOUTH);
     JFrame cerceve=new JFrame(bb);
     cerceve.addWindowListener(new BasicWindowMonitor());
     cerceve.getContentPane().add(new JScrollPane(jpan));
     cerceve.pack();
     cerceve.setVisible(true);
	 }
	 
     public String atombalance()
     {String s=" |";
      for(int i=0;i<name.length;i++) 
        {  if(name[i].length()==2) s+=name[i]+"   ";
	       else if(name[i].length()==2) s+=name[i]+"  ";
           else if(name[i].length()==3) s+=name[i]+" ";
           else if(name[i].length()>=4) s+=name[i];
        }
      s+="|b0  b1 |\n";
      for(int j=0;j<atomList.length;j++) 
      {s+=atomsymbols[j]+"|";
       for(int i=0;i<name.length;i++) 
       {s+=A[j][i]+" ";}
       s+=" |"+b0[j]+" "+b1[j]+"|\n";
      }
     return s;
     }

     public double Taf(double TR,double xl,double xu)
     {
      double TR1,xl1,xu1;
      TR1=TR;xl1=xl;xu1=xu;
     // Adyabatic flame temperature using Bisection method
     // bisection method to find roots of zero energy change
     // Q=0
     // defination of variables :
     // xl : lower guess
     // xu : upper guess
     // xr : root estimate
     // es : stopping criterion
     // ea :approximate error
     // maxit : maximum iterations
     // iter  : number of iteration
     double test;
     double xr=0;
     double es,ea;
     double fxl=0,fxr=0;
     int maxit=500,iter=0;
     es=0.000001;
     ea=1.1*es;
     while((ea>es)&&(iter<maxit))
     {
     xr=(xl1+xu1)/2.0;
     iter++;
     if((xl1+xu1)!=0)
        { ea=Math.abs((xu1-xl1)/(xl1+xu1))*100;}
     fxl= H(TR,xl1);
     fxr= H(TR,xr);
     test= fxl*fxr;
     if(test==0.0)       ea=0;
     else if(test<0.0)  xu1=xr;
     else
       {
       xl1=xr;
       }
     } //end of while
        return xr;
     }
     
     double Vi(double TR,double TP,int Ni)
     {return -G(TR,TP)/(96487*Ni);}
	 
	 double Vi0(double TR,double TP,int Ni)
     {return -G0(TR,TP)/(96487*Ni);}
}
