// Calculate energy band diagram of a pn junction.
// (Java 1.1 or later version)
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.lang.String.*;
import java.lang.Double.*;
import java.lang.Math.*;

public class PNJunction extends Applet implements ActionListener
{

   TextField naField, ndField, niField, ncField, nvField, tField, vField;
   String message = ""; // String containing system messages

   double na;		// Density of acceptor impurity atoms -- p-type(cm^-3)
   double nd;		// Density of donor impurity atoms -- n-type(cm^-3)
   double ni;		// Intrinsic concentration of electrons(cm^-3)
   double temperature;	// Temperature(K) 
   double vApplied;	// Applied Potential (V) (-Vr)


   double k = 1.38E-23;		// Boltzmann's Constant(J/K)
   double kev = 8.62E-5;	// Boltzmann's Constant(eV/K)
   double hbar = 1.054E-34;	// Planck's Constant(J*sec)
   double h = 6.625E-34;	// Plank's Constant(J*sec)
   double pi = 3.14159;		// pI
   double m0 = 9.11E-31;	// Electron mass(kg)
   double e = 1.6E-19;		// Charge on an electron(Coulombs)
   double epsilon0 = 8.85E-14;	// Permittivity of Free Space(F/cm)
   double nc = 2.8E19;		// Density of states - conduction band(cm^-3)
   double nv = 1.04E19;		// Density of states - valence band(cm^-3)

   double phiFN;			// Potential diff. between Efi and Ef, n-type
   double phiFP;                 // Potential diff. between Efi and Ef, p-type
   double vbi;			// Built in voltage level.
   double phiCFP;		// Ec - EF potential p-type
   double phiCFN;                // Ec - EF potential n-type
   double phiFVP;		// Ef - Ev potential p-type
   double phiFVN;                // Ef - Ev potential n-type

   Color blue = new Color( 0, 0, 255 );
   Color red = new Color( 255, 0, 0 );
   Color green = new Color( 0, 255, 0 );
   Color black = new Color( 0, 0, 0 );
   Color white = new Color( 255, 255, 255 );


   public void init()
   {
	Label naLabel = new Label( "Density of acceptor atoms p-type(cm^-3): ", Label.RIGHT );
	Label ndLabel = new Label( "Density of donor atoms n-type(cm^-3): ", Label.RIGHT );
	Label niLabel = new Label( "Intinsic concentration of electrons(cm^-3): ", Label.RIGHT );
	Label ncLabel = new Label( "Effective density of states in the conduction band(cm^-3): ", Label.RIGHT );
	Label nvLabel = new Label( "Effective density of states in the valence band(cm^-3): ", Label.RIGHT );
	Label tLabel = new Label( "Temperature(K): ", Label.RIGHT );
	Label vLabel = new Label( "Applied Potential(mV): ", Label.RIGHT );

	naField = new TextField( 20 );
	ndField = new TextField( 20 );
	niField = new TextField( 12 );
	ncField = new TextField( 20 );
	nvField = new TextField( 20 );
	tField = new TextField( 4 );
	vField = new TextField( 5 );


	// Add controls
	add( naLabel );
	add( naField );
	add( ndLabel );
	add( ndField );
	add( niLabel );
	add( niField );
	add( ncLabel );
	add( ncField );
	add( nvLabel );
	add( nvField );
	add( tLabel );
	add( tField );
	add( vLabel );
	add( vField );


	// Register ActionListeners to receive action events.
	naField.addActionListener( this );
	ndField.addActionListener( this );
	niField.addActionListener( this );
	ncField.addActionListener( this );
	nvField.addActionListener( this );
	tField.addActionListener( this );
	vField.addActionListener( this );

   }

   // ActionListeners.
   public void actionPerformed( ActionEvent ae )
   {
	repaint();
   }

   public void paint( Graphics g )
   {

	message = "";

	try
	{
		na = 1 * (double)Long.parseLong( naField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Na\" field must contain a number: " + exceptionText;
		na = 1.0;
	}
	try
	{
		nd = 1 * (double)Long.parseLong( ndField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Nd\" field must contain a number: " + exceptionText;
		nd = 1.0;
	}
	try
	{
		ni = 1 * (double)Long.parseLong( niField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"ni\" field must contain a number: " + exceptionText;
		ni = 1.5E10;	// Silicon intrinsic concentration of e-
	}
	try
	{
		nc = 1 * (double)Long.parseLong( ncField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Nc\" field must contain a number: " + exceptionText;
		nc = 2.8E19;	// Silicon effective density of states CB
	}
	try
	{
		nv = 1 * (double)Long.parseLong( nvField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Nv\" field must contain a number: " + exceptionText;
		nv = 1.04E19;	// Silicon effective density of states VB
	}
	try
	{
		temperature = 1 * (double)Long.parseLong( tField.getText() );	
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"T\" field must contain a number: " + exceptionText;
		temperature = 300.0;
	}
	try
	{
		vApplied = 1E-3 * (double)Long.parseLong( vField.getText() );	
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Vapplied\" field must contain a number: " + exceptionText;
		vApplied = 0.0;
	}

	
	
	
	// Calculate Vbi, built in voltage
	phiFN = -(k*temperature/e)*Math.log((nd)/(ni * ni));
	phiFP = (k*temperature/e)*Math.log((na)/(ni * ni));
	vbi = Math.abs(phiFN) + Math.abs(phiFP) - vApplied;

	phiCFP = (k*temperature/e)*Math.log(nc/((ni * ni)/na));
	phiCFN = (k*temperature/e)*Math.log(nc/nd);
	phiFVP = (k*temperature/e)*Math.log(nv/na);
	phiFVN = (k*temperature/e)*Math.log(nv/((ni * ni)/nd));


	// Write out Input values
	g.drawString( "Na(cm^-3): " + na, 6 ,200 );
	g.drawString( "Nd(cm^-3): " + nd, 6, 225 );
	g.drawString( "ni(cm^-3): " + ni, 6, 250 );
	g.drawString( "T(K): " + temperature, 6, 275 );
	g.drawString( "Applied Potential(V): " + vApplied, 6, 300 );
	// Write out calculated values
	g.drawString( "phiCFn(V): " + phiCFN, 6, 350 );
	g.drawString( "phiFn(V): " + phiFN, 6, 375 );
	g.drawString( "phiFVn(V): " + phiFVN, 6, 400 );
	g.drawString( "phiCFp(V): " + phiCFP, 6, 450 );
	g.drawString( "phiFp(V): " + phiFP, 6, 475 );
	g.drawString( "phiFVp(V): " + phiFVP, 6, 500 );
	g.drawString( "Vbi(V): " + vbi, 6, 550 );

	// Draw Fermi energy
	g.setColor(blue);
	g.drawLine(300, (int)(350 - (vApplied * 12.5)), 410, (int)(350 - (vApplied * 12.5)));
	g.drawLine(390, (int)(350 + (vApplied * 12.5)), 500, (int)(350 + (vApplied * 12.5)));
	// Draw Quasi-Fermi energy for holes.
	g.setColor(black);
	g.drawLine(300, (int)(350 - (vApplied * 12.5) - (phiFP * 25)), 390, (int)(350 - (vApplied * 12.5) - (phiFP * 25)));
	// Draw Quasi-Fermi energy for electrons.
	g.drawLine(410, (int)(350 + (vApplied * 12.5) - (phiFN * 25)), 500, (int)(350 + (vApplied * 12.5) - (phiFN * 25)));
	// Draw conncetion of Quasi-Fermi energy levels
	g.drawLine(390, (int)(350 - (vApplied * 12.5) - (phiFP * 25)), 410, (int)(350 + (vApplied * 12.5) - (phiFN * 25)));

	// Draw Conduction band
	g.setColor(red);
	g.drawLine(300, (int)(350 - (phiCFP * 25) - (vApplied * 12.5) - (phiFP * 25)), 390, (int)(350 - (phiCFP * 25) - (vApplied * 12.5) - (phiFP * 25)));
	g.drawLine(410, (int)(350 - (phiCFN * 25) + (vApplied * 12.5) - (phiFN * 25)), 500, (int)(350 - (phiCFN * 25) + (vApplied * 12.5) - (phiFN * 25)));
	// Draw connection of conduction band
	g.drawLine(390, (int)(350 - (phiCFP * 25) - (vApplied * 12.5) - (phiFP * 25)), 410, (int)(350 - (phiCFN * 25) + (vApplied * 12.5) - (phiFN * 25)));

	// Draw Valence band
	g.setColor(green);
	g.drawLine(300, (int)(350 + (phiFVP * 25) - (vApplied * 12.5) - (phiFP * 25)), 390, (int)(350 + (phiFVP * 25) - (vApplied * 12.5) - (phiFP * 25)));
	g.drawLine(410, (int)(350 + (phiFVN * 25) + (vApplied * 12.5) - (phiFN * 25)), 500, (int)(350 + (phiFVN * 25) + (vApplied * 12.5) - (phiFN * 25)));
	// Draw connection of conduction band
	g.drawLine(390, (int)(350 + (phiFVP * 25) - (vApplied * 12.5) - (phiFP * 25)), 410, (int)(350 + (phiFVN * 25) + (vApplied * 12.5) - (phiFN * 25)));
	g.setColor(black);

	// Write out any messages
	g.drawString( "Message: " + message, 6, 600 );

   }

   // main() is the entry point when called as an application.
   // main() is not used when run as an applet.
   public static void main ( String args[] )
   {
	Frame mainWindow = new Frame ( "PNJunction" );
	PNJunction application = new PNJunction ();

	mainWindow.setSize ( 600, 600 );
	mainWindow.add ( "Center", application );
	mainWindow.show ();
	application.init();
   }

}
