import java.awt.*;
import java.util.*;
import java.applet.*;
import graph.*;

/*
**************************************************************************
**
**                      Applet JC 2
**
**************************************************************************
**    Copyright (C)
**
**************************************************************************
*
* This applet uses
*
*************************************************************************/

public class e_fm extends Applet {

      G2Dint graph1        = new G2Dint();   // Graph class to do the plotting
      G2Dint graph2        = new G2Dint();
      G2Dint graph3        = new G2Dint();
      Axis xaxis1;
      Axis yaxis1;
      Axis xaxis2;
      Axis yaxis2;
      Axis xaxis3;
      Axis yaxis3;
      DataSet data1a;
      DataSet data2a;
      DataSet data3a;
      DataSet data1b;
      DataSet data2b;
      DataSet data3b;
      int     Change_a  = 1;

      TextField NDinput              = new TextField(13);      // Number of Donors
      TextField EDinput              = new TextField(13);      // Energy of Donorlevel
      TextField NAinput              = new TextField(13);      // Number of Aceptors
      TextField EAinput              = new TextField(13);      // Energy of Aceptorlevel
      TextField XFinput              = new TextField(13);      // X_Parsefunction
      TextField YFinput              = new TextField(13);      // Y_Parsefunction
      Button plot                    = new Button("Plot It!"); // Button to plot it.
      double 	ND;
      double 	ED;
      double    NA;
      double 	EA;
      double 	kT;
      double    Eg = 1.12;
      double    VV;
      double    VVkT;

      double null_fu(double EF){
       double ExH,ExD,ExE,ExA;

       ExH = -EF/kT;
       if (ExH >(-1e+20)){
          ExH = Math.exp(ExH);
       } else {
       ExH = 0;
       };
       ExD = (EF-ED)/kT;
       if (ExD >(-1e+20)){
          ExD = Math.exp(ExD);
       } else {
       ExD = 0;
       };
       ExE = -(Eg-EF)/kT;
       if (ExE >(-1e+20)){
          ExE = Math.exp(ExE);
       } else {
       ExE = 0;
       };
       ExA = (EA-EF)/kT;
       if (ExA >(-1e+20)){
          ExA = Math.exp(ExA);
       } else {
       ExA = 0;
       };
       ExD = ND/(1+ExD);
       ExA = NA/(1+ExA);
       ExE = VVkT*(ExH-ExE)+ExD-ExA;
       return ExE;
      }

      double fermi_energy(){
       double EFL,EFR,EFM,Delta,WEFL,WEFR,WEFM;
       EFL = 0;
       EFR = Eg;
       WEFL = null_fu(EFL);
       WEFR = null_fu(EFR);
       EFM = 0.5*Eg; 
       Delta = Eg;
       WEFM = 1;
       while ( ( WEFM > (1e-6)) & (Delta > (1e-7)) ){
        EFM = 0.5*(EFL+EFR);
        WEFM = null_fu(EFM);
        if (WEFM>0) {
          if (WEFL>0) {
             EFL  = EFM;
             WEFL = WEFM;
          } else {
             EFR  = EFM;
             WEFR = WEFM;
          }
        } else {
          if (WEFL>0) {
             EFR  = EFM;
             WEFR = WEFM;
          } else {
             EFL  = EFM;
             WEFL = WEFM;
          }
        }
       WEFM = Math.abs(WEFM);  
       Delta = Math.abs(EFL-EFR);      
       }
       return EFM;
      }

      public void init() {
      	 Label title            = new Label("Fermi Energy of Silicon (E gap = 1.12eV)",Label.CENTER);
      	 Panel panel            = new Panel();
         GridBagLayout gridbag  = new GridBagLayout();
         GridBagConstraints  c  = new GridBagConstraints();
         Font font              = new Font("TimesRoman",Font.PLAIN,15);

         title.setFont(new Font("TimesRoman",Font.PLAIN,25));


         setLayout(new BorderLayout() );
         add("North",title);
         add("Center",panel);


         NDinput.setText(getParameter("ND"));
         EDinput.setText(getParameter("ED"));
         NAinput.setText(getParameter("NA"));
         EAinput.setText(getParameter("EA"));
         XFinput.setText(getParameter("XFu"));
         YFinput.setText(getParameter("YFu"));


         panel.setLayout(gridbag);


         Label NDlabel          = new Label("Concentration of Donors [1e15/cm^3]");
         Label EDlabel          = new Label("Energy Level of Donor state [eV]");
         Label NAlabel          = new Label("        Concentration of Acceptors [1e15/cm^3]");
         Label EAlabel          = new Label("        Energy Level of Acceptor state [eV]");
         Label XFlabel          = new Label("   xFu: X-Axis Scale-function");
         Label YFlabel          = new Label("   yFu: Y-Axis Scale-function");


         NDlabel.setFont(font);
         EDlabel.setFont(font);
         NAlabel.setFont(font);
         EAlabel.setFont(font);
         XFlabel.setFont(font);
         YFlabel.setFont(font);

         NDinput.setFont(font);
         NDinput.setBackground(Color.lightGray);
         EDinput.setFont(font);
         EDinput.setBackground(Color.lightGray);
         NAinput.setFont(font);
         NAinput.setBackground(Color.lightGray);
         EAinput.setFont(font);
         EAinput.setBackground(Color.lightGray);
         XFinput.setFont(font);
         XFinput.setBackground(Color.lightGray);
         YFinput.setFont(font);
         YFinput.setBackground(Color.lightGray);

         plot.setFont(font);
         plot.setBackground(Color.green);

//	GRAPH

         c.weightx = 1.0;
         c.weighty = 1.0;
         c.gridwidth = 3;
         c.gridwidth = GridBagConstraints.REMAINDER;
         c.fill = GridBagConstraints.BOTH;
         gridbag.setConstraints(graph1,c);
         gridbag.setConstraints(graph2,c);
         gridbag.setConstraints(graph3,c);


// 	PLOT

         c.fill = GridBagConstraints.NONE;
         c.weightx=0.0;
         c.weighty=0.03;
         c.gridheight=1;
         c.anchor = GridBagConstraints.CENTER;
         gridbag.setConstraints(plot,c);


//	NDINPUT
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(NDlabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         gridbag.setConstraints(NDinput,c);

//      EDINPUT
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(EDlabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         c.fill = GridBagConstraints.EAST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(EDinput,c);

//	NAINPUT
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(NAlabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         gridbag.setConstraints(NAinput,c);

//      EAInput
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(EAlabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(EAinput,c);

//	XFINPUT
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(XFlabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         gridbag.setConstraints(XFinput,c);

//      YFInput
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(YFlabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(YFinput,c);


         panel.add(graph1);
         panel.add(graph2);
         panel.add(graph3);
         panel.add(plot);
         panel.add(NDlabel);
         panel.add(NDinput);
         panel.add(EDlabel);
         panel.add(EDinput);
         panel.add(NAlabel);
         panel.add(NAinput);
         panel.add(EAlabel);
         panel.add(EAinput);
         panel.add(XFlabel);
         panel.add(XFinput);
         panel.add(YFlabel);
         panel.add(YFinput);

//	Graph Plot 1

         xaxis1 = graph1.createXAxis();
         xaxis1.setTitleText("xFu(T [1000 K])");
         yaxis1 = graph1.createYAxis();


         data1a = new DataSet();

         xaxis1.attachDataSet(data1a);
         yaxis1.attachDataSet(data1a);
         graph1.attachDataSet(data1a);

         data1b = new DataSet();

         xaxis1.attachDataSet(data1b);
         yaxis1.attachDataSet(data1b);
         graph1.attachDataSet(data1b);


         graph1.setDataBackground(new Color(255,255,255));
         graph1.setBackground(new Color(240,240,240));

//      Graph Plot 2

         xaxis2 = graph2.createXAxis();
         xaxis2.setTitleText("xFu(T [1000 K])");

         yaxis2 = graph2.createYAxis();


         data2a = new DataSet();

         xaxis2.attachDataSet(data2a);
         yaxis2.attachDataSet(data2a);
         graph2.attachDataSet(data2a);

         data2b = new DataSet();

         xaxis2.attachDataSet(data2b);
         yaxis2.attachDataSet(data2b);
         graph2.attachDataSet(data2b);


         graph2.setDataBackground(new Color(255,255,255));
         graph2.setBackground(new Color(240,240,240));

//      Graph Plot 3

         xaxis3 = graph3.createXAxis();
         xaxis3.setTitleText("xFu(T [1000 K])");

         yaxis3 = graph3.createYAxis();


         data3a = new DataSet();

         xaxis3.attachDataSet(data3a);
         yaxis3.attachDataSet(data3a);
         graph3.attachDataSet(data3a);

         data3b = new DataSet();

         xaxis3.attachDataSet(data3b);
         yaxis3.attachDataSet(data3b);
         graph3.attachDataSet(data3b);


         graph3.setDataBackground(new Color(255,255,255));
         graph3.setBackground(new Color(240,240,240));


         VV = 2*3.14159*3.0*9.11*2.418/6.626;
         VV = Math.sqrt(VV);
         VV = 2000*VV*VV*VV;
     
         plot();

      }

      void plot() {
         int 		Points = 400;
         double         kT_max = 0.14;
         double         kT_min = 0.001;
         double         h1,h2,h3;
         int 		count = 0;
         boolean 	error = false;

//     READ ND
       try {
            ND = Double.valueOf(NDinput.getText()).doubleValue();
         } catch(Exception e) {
              this.showStatus("Error with ND value!");
              System.out.println("Input Error "+e.getMessage());
              return;
         }
//     READ ED
       try {
            ED = Double.valueOf(EDinput.getText()).doubleValue();
         } catch(Exception e) {
              this.showStatus("Error with ED value!");
              System.out.println("Input Error "+e.getMessage());
              return;
         }
//     READ NA
       try {
            NA = Double.valueOf(NAinput.getText()).doubleValue();
         } catch(Exception e) {
              this.showStatus("Error with NA value!");
              System.out.println("Input Error "+e.getMessage());
              return;
         }
//     READ EA
       try {
            EA = Double.valueOf(EAinput.getText()).doubleValue();
         } catch(Exception e) {
              this.showStatus("Error with EA value!");
              System.out.println("Input Error "+e.getMessage());
              return;
         }

//     READ x-function
         ParseFunction x_fun = new ParseFunction(XFinput.getText());

         if(!x_fun.parse()) {
              this.showStatus("Failed to parse X-function!");
              System.out.println("Failed to parse X-function!");
              return;
         }

//     READ y-function
         ParseFunction y_fun = new ParseFunction(YFinput.getText());

         if(!y_fun.parse()) {
              this.showStatus("Failed to parse Y-function!");
              System.out.println("Failed to parse Y-function!");
              return;
         }

         double d1[] = new double[2*Points];
         double d2[] = new double[2*Points];
         double d3[] = new double[2*Points];

         this.showStatus("Calculating points!");

         for(int i=0; i<Points; i++) {
             kT = kT_min + i*(kT_max-kT_min)/(Points-1);
             try {
                   h1 = Math.sqrt(kT);
                   VVkT = VV*h1*h1*h1;
                   h3 = kT/0.025*0.3;
                   h3 = x_fun.getResult(h3);
                   d1[count] = h3;
                   d2[count] = h3;
                   d3[count] = h3;
                   h1 = fermi_energy();
                   d1[count+1] = h1;
                   h2 = (Math.log(VVkT*1e15)-(Eg-h1)/kT);
                   if (h2<0) {
                     h2 = 0;
                   }
                   h2 = y_fun.getResult(Math.exp(h2));
                   d2[count+1] = h2;

                   h2 = (Math.log(VVkT*1e15)-h1/kT);
                   if (h2<0) {
                     h2 = 0;
                   }
                   h2 = y_fun.getResult(Math.exp(h2));
                   d3[count+1] = h2;

                   count += 2;
             } catch(Exception e) { error = true; }

         }

         if(count <= 2) {
             this.showStatus("Error NO POINTS to PLOT!");
             System.out.println("Error NO POINTS to PLOT!");
             return;
         } else
         if( error ) {
             this.showStatus("Error while Calculating points!");
             System.out.println("Error while calculating points!");
	 }


         yaxis1.setTitleText("E_{Fermi} [eV]");
         yaxis2.setTitleText("yFu(N_{electron})");
         yaxis3.setTitleText("yFu(N_{holes})");

         Change_a = (~ Change_a);

         if( Change_a==1) {
                        data1a.deleteData();
                        data2a.deleteData();
                        data3a.deleteData();

                        try {
                             data1a.append(d1,count/2);
                             data1a.linecolor = Color.red;
                             data2a.append(d2,count/2);
                             data2a.linecolor = Color.red;
                             data3a.append(d3,count/2);
                             data3a.linecolor = Color.red;

                            } catch(Exception e) {
                        this.showStatus("Error while appending data!");
                        System.out.println("Error while appending data!");
                        return;
	                }
                        }
                   else {
                        data1b.deleteData();
                        data2b.deleteData();
                        data3b.deleteData();

                        try {
                             data1b.append(d1,count/2);
                             data1b.linecolor = Color.blue;
                             data2b.append(d2,count/2);
                             data2b.linecolor = Color.blue;
                             data3b.append(d3,count/2);
                             data3b.linecolor = Color.blue;

                            } catch(Exception e) {
                        this.showStatus("Error while appending data!");
                        System.out.println("Error while appending data!");
                        return;
	                }
                        }

try{
         graph1.repaint();
         graph2.repaint();
         graph3.repaint();

           } catch(Exception e) {
                        this.showStatus("Error while drawing data!");
                        System.out.println("Error while drawing data!");
                        return;
	                }
      }



     public boolean action(Event e, Object a) {

         if(e.target instanceof Button) {
             if( plot.equals(e.target) ) {
                  plot();
                  return true;
             }
         }


         return false;
       }
}
