/** applet No. 1252 * * p-n diode - Monte-Carlo simulation 3D * - multi thread MCS3D :: display - asynchronous * * Created by Ikeuchi Mitsuru on January 20 2008. * Copyright (c) 2008 Ikeuchi Mitsuru. All rights reserved. * * ver 0.0.1 2008.01.20 created * */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class pnDiodeMCS3D extends Applet implements MouseListener, MouseMotionListener, ItemListener, ActionListener, AdjustmentListener, Runnable { // ------------------------------------ preset field ----------- Thread th = null; // for run()-paint() thread Thread thmcs = null; // for MCS3D thread MCS3D mcs = new MCS3D(); // create MCS3D instance // for event Choice ch_dir, ch_view; Button bt_reset, bt_startStop, bt_step; Scrollbar sc_gate, sc_depth; // for off-paint buffer Dimension dim; Image imgOff; Graphics gOff; // display private int sleepTime = 30; // sleep time (ms) private int dispWidth = 630; private int dispHeight = 460; private int dispMode = 0; private double boxDispWidth = 320.0; private double dispScale = 1.0; private double viewScale = 1.0; private double viewDepth = 0.5; private double xShift = 0.0; private double yShift = 0.0; private int gx0 = 60; private int gy0 = 90; private int xImageLoc = gx0; private int yImageLoc = gy0; private double viewTheta = -15.0*3.14/180.0; private double viewFai = -60.0*3.14/180.0; private double cosTh = Math.cos(viewTheta); private double sinTh = Math.sin(viewTheta); private double cosFi = Math.cos(viewFai); private double sinFi = Math.sin(viewFai); private int xpts[] = new int[400]; private int ypts[] = new int[400]; private double fpts[] = new double[400]; int dgX, dgY, dgXb,dgYb; // mouse private int thCount = 0; // ------------------------------ applet main thread ----------- public void init() { resize(dispWidth,dispHeight); setBackground(Color.white); dim = getSize(); imgOff = createImage(dim.width,dim.height); gOff = imgOff.getGraphics(); ch_dir = new Choice(); ch_dir.add("positive"); ch_dir.add("0"); ch_dir.add("negative"); ch_dir.addItemListener(this); ch_dir.select("0"); ch_view = new Choice(); ch_view.add("3D-plot"); ch_view.add("z-depth"); ch_view.add("grid pot"); ch_view.addItemListener(this); ch_view.select("3D plot"); bt_reset = new Button("reset"); bt_reset.addActionListener(this); bt_startStop= new Button("start/stop"); bt_startStop.addActionListener(this); bt_step = new Button("step"); bt_step.addActionListener(this); sc_gate = new Scrollbar(Scrollbar.HORIZONTAL,200,10,0,510); sc_gate.addAdjustmentListener(this); sc_depth = new Scrollbar(Scrollbar.HORIZONTAL,50,10,0,110); sc_depth.addAdjustmentListener(this); addMouseListener(this); addMouseMotionListener(this); setLayout(new BorderLayout()); Panel pnl = new Panel(); pnl.setLayout(new GridLayout(1,6,5,0)); // pnl.add(new Label(" ")); pnl.add(bt_reset); pnl.add(bt_startStop); pnl.add(bt_step); pnl.add(ch_dir); pnl.add(sc_depth); pnl.add(ch_view); add(pnl,"North"); } public void start() { if (thmcs == null) { thmcs = new Thread(mcs); thmcs.start(); } if (th == null) { th = new Thread(this); th.start(); } } public void stop() { if (th != null) th = null; if (thmcs != null) thmcs = null; } // ---------------------------------- event listener ----------- public void itemStateChanged(ItemEvent ev){ if (ev.getSource() == ch_dir) { mcs.setcdir( 1 - ch_dir.getSelectedIndex() ); } else if (ev.getSource() == ch_view) { dispMode = ch_view.getSelectedIndex(); } } public void actionPerformed(ActionEvent ev){ if (ev.getSource() == bt_reset){ mcs.reset(); thCount = 0; } else if (ev.getSource() == bt_startStop){ if (mcs.getStartSW()==0) { mcs.setStartSW(1); } else { mcs.setStartSW(0); } } else if (ev.getSource() == bt_step){ if (mcs.getStartSW()==0) { mcs.setStepSW(); } } } public void adjustmentValueChanged(AdjustmentEvent ev){ double vs; if (ev.getSource() == sc_depth) { viewDepth = 0.01*(double)(sc_depth.getValue()); } else if (ev.getSource() == sc_gate) { mcs.setGatePotential( 0.01*(double)(sc_gate.getValue()) - 2.0); } } public void mousePressed(MouseEvent ev){ } public void mouseReleased(MouseEvent ev){ dgXb = 0; dgYb = 0; dgX = 0; dgY = 0; } public void mouseClicked(MouseEvent ev){ } public void mouseEntered(MouseEvent ev){ } public void mouseExited (MouseEvent ev){ } public void mouseMoved (MouseEvent ev){ } public void mouseDragged(MouseEvent ev){ dgXb = dgX; dgYb = dgY; dgX=ev.getX(); dgY=ev.getY(); if (dgXb==0 && dgYb==0) { dgXb = dgX; dgYb = dgY; } if (dispMode==0 || dispMode==1 || dispMode==2) { viewTheta += 0.5*3.14159/180.0*(dgX-dgXb); viewFai += 0.5*3.14159/180.0*(dgY-dgYb); cosTh = Math.cos(viewTheta); sinTh = Math.sin(viewTheta); cosFi = Math.cos(viewFai); sinFi = Math.sin(viewFai); } else { xShift += (1.0/viewScale/dispScale)*(dgX-dgXb); yShift += (1.0/viewScale/dispScale)*(dgY-dgYb); xImageLoc = gx0+(int)(dispScale*viewScale*xShift); yImageLoc = gy0+(int)(dispScale*viewScale*yShift); } } // ========================= run() - paint() loop ============== public void run() { while (th != null) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } thCount += 1; offPaint(); repaint(); } } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { g.drawImage(imgOff,0,0,this); } // --------------------------------------- off-paint ----------- private void offPaint() { gOff.setColor(Color.white); gOff.fillRect(0,0,dim.width,dim.height); if (dispMode==0) { walker3DPlot(60,90,1.0); } else if (dispMode==1) { walker3DPlot(60,90,viewDepth); } else if (dispMode==2) { gridPlot(60,90,viewDepth); } else if (dispMode==3) { ; } else if (dispMode==4) { ; } gOff.setColor(Color.blue); gOff.drawString("t="+mcs.getTime()+" ",10,40); gOff.setColor(Color.black); if (mcs.getStartSW()==0) { gOff.drawString("stopped",dispWidth/6*1+10,40); } else { gOff.drawString("started",dispWidth/6*1+10,40); } gOff.drawString("current",dispWidth/6*3+10,40); gOff.drawString("z="+(int)(viewDepth*100.0)+"%",dispWidth/6*4+10,40); gOff.drawString("view",dispWidth/6*5+10,40); gOff.setColor(Color.cyan); gOff.drawString("Nelec="+mcs.getNparticles(-1)+" ",dispWidth/6*0+10,60); gOff.setColor(Color.magenta); gOff.drawString("Nhole="+mcs.getNparticles(1)+" ",dispWidth/6*1+10,60); gOff.setColor(Color.black); gOff.drawString("I="+(int)(mcs.getMeanCurrent()*100.0)/100.0+"",dispWidth/6*3+10,60); gOff.setColor(Color.black); gOff.drawString("count MD="+mcs.getCount()+" ",400,440); gOff.drawString("disp="+thCount+" ",530,440); gOff.drawString("Vnn="+(float)mcs.potentialOfN()+" ",30,440); gOff.drawString("Vpp="+(float)mcs.potentialOfP()+" ",230,440); } // ------------------------------------ plot methods ----------- private void walker3DPlot(int gbx, int gby, double depth) { int i, j, k, knd, ix, iy, ir, NNx, NNy,NNz, nz; float col; double sc,x,y,z,cxx,cyy,czz, ppx,ppy,ppz; NNx = mcs.getNNx(); NNy = mcs.getNNy(); NNz = mcs.getNNz(); nz = (int)(depth*NNz); sc = (480.0/NNx); cxx = 0.5*sc*NNx; cyy = 0.5*sc*NNy; czz = 0.5*sc*NNz; ir = (int)sc; if (ir<1) ir = 1; for (i=0; i0.0) { d = (float)(0.5*f+0.1); if (d>=0.99f) d=0.99f; } else { f = -f; d = (float)(0.5*f+0.1); if (d>=0.99f) d=0.99f; } gOff.setColor(Color.getHSBColor(col,s,d)); } } // =================== Monte-Carlo simulation 3D class =========== class MCS3D implements Runnable { private int t = 0; // system time private int dt = 1; // time division // private int hh = 1; // space division v0=hh/dt private int NBlock = 4; private int Nsx = 48; private int Nsy = 32; private int Nsz = 32; private int NNx = Nsx*NBlock; private int NNy = Nsy*NBlock; private int NNz = Nsy*NBlock; private double alpha = 1.0; // vd/v0 = a = alpha E ; drift velocity private int cdir = 0; // current direction { -1, 0, 1 } private double pExtinction = 0.5; // electron-hole collision-extinction probability private double gatePotential = 0.0; private double iMean = 0.0; // mean current (through current source) private double issMean = 0.0; private double iddMean = 0.0; // point difinition private int p_x1 = 4*8; private int p_x2 = p_x1 + 4*16; private int p_x3 = p_x2 + 4*16; private int p_y1 = 4*8; private int p_y2 = p_y1 + 4*16; private int p_z1 = 4*8; private int p_z2 = p_z1 + 4*16; // region difinition .... xPos, yPos, zPos, xSize, ySize, zSize private int region_world[] = { 0, 0, 0, NNx, NNy, NNz }; private int region_n[] = { p_x1, p_y1, p_z1, p_x2-p_x1, p_y2-p_y1, p_z2-p_z1 }; // n-type private int region_p[] = { p_x2, p_y1, p_z1, p_x3-p_x2, p_y2-p_y1, p_z2-p_z1 }; // p-type private int region_nTerm[] = { p_x1, p_y1+12, p_z1+8, 12, p_y2-p_y1-16, p_z2-p_z1-16 }; // n terminal private int region_pTerm[] = { p_x3-12, p_y1+8, p_z1+8, 12, p_y2-p_y1-16, p_z2-p_z1-16 }; // p terminal private int NNp = 100000; // number of particles private int NN = 100000; private byte kind[] = new byte[NN]; // particle kind -1-electron, 0-dead, 1-hole private int px[] = new int[NN]; // particle x-pos private int py[] = new int[NN]; // particle y-pos private int pz[] = new int[NN]; // particle y-pos private byte field[][][] = new byte[NNx][NNy][NNz]; // -2-acceptor,-1-electron, 0-space, 1-hole, 2-donor, 3-wall private float potential[][][] = new float[Nsx][Nsy][Nsz]; // potential private float charge[][][] = new float[Nsx][Nsy][Nsz]; // charge private int sleepTime = 1; private int stopSleepTime = 100; private int resetSW = 0; private int startSW = 1; private int stepSW = 0; private int statMode = 2; private int count = 0; // ------------------------------- class constructor ----------- MCS3D() { setInitialCondition(); } // -------------------------------------- thread run ----------- public void run() { while (true) { count += 1; timeEvolution(); if (sleepTime>0) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } } // --------------------------- set initial condition ----------- private void setInitialCondition() { int i, ix, iy; t = 0; count = 0; fillField(3, region_world); //clear (outer space = 3) i = 0; i = setNtype(i, region_n); // n-type i = setPtype(i, region_p); // p-type NNp = i; initPotential(); } private int setNtype(int ip, int region[]) { // n-type semiconductor int ii; fillField(0, region); // inner space = 0 ii = ip; ii = setBlock(ii,-1, 1, 1, 1, region); // electron ii = setBlock(ii, 2, 2, 2, 2, region); // donor return ii; } private int setPtype(int ip, int region[]) { // p-type semiconductor int ii; fillField(0, region); // inner space = 0 ii = ip; ii = setBlock(ii, 1, 1, 2, 1, region); // hole ii = setBlock(ii,-2, 2, 1, 2, region); // acceptor return ii; } private int setItype(int ip, int region[]) { // intrinsic semiconductor fillField(0, region); // inner space = 0 return ip; } private void fillField(int f, int region[]) { int ix,iy,iz, xPos,yPos,zPos, xSize,ySize,zSize; xPos = region[0]; yPos = region[1]; zPos = region[2]; xSize = region[3]; ySize = region[4]; zSize = region[5]; for (ix=xPos; ix=1+a) { ix = px[i]+1; } else { ix = px[i]-1; } iy = py[i]; iz = pz[i]; } else if (r<4.0) { // y-direction r = r - 2.0; ix = px[i]; a = alpha*k*eyField(px[i],py[i],pz[i]); if (r>=1+a) { iy = py[i]+1; } else { iy = py[i]-1; } iz = pz[i]; } else { // z-direction r = r - 4.0; ix = px[i]; iy = py[i]; a = alpha*k*ezField(px[i],py[i],pz[i]); if (r>=1+a) { iz = pz[i]+1; } else { iz = pz[i]-1; } } move(i,ix,iy,iz); } q = 0; if (cdir>=0 || potentialOf(region_nTerm)<1.0) { q = currentSource(0.5*cdir, region_pTerm, region_nTerm); } iMean = 0.001*q + 0.999*iMean; } private int move(int i, int ix, int iy, int iz) { int ib,jb,kb,irem; if (ix<0 || ix>=NNx || iy<0 || iy>=NNy || iz<0 || iz>=NNz) return 0; if (field[ix][iy][iz]!=0) { ib = px[i]; jb = py[i]; kb = pz[i]; if (field[ix][iy][iz]*field[ib][jb][kb]!=-1) return 0; // electron - hole extinction if (Math.random()>pExtinction) return 0; removeParticle(i); irem = searchParticle(ix,iy,iz); if (irem>=0) removeParticle(irem); return 0; } ib = px[i]; jb = py[i]; kb = pz[i]; field[ib][jb][kb] = 0; field[ix][iy][iz] = kind[i]; px[i] = ix; py[i] = iy; pz[i] = iz; return -1; } // set charge private void setCharge() { int i,j,k, ii,jj,kk, knd,cg; for (i=1; i1.02*pot) { ip = putParticle(-1, region); if (ip>=0) q = -1; } else if (p<0.98*pot) { ip = removableParticleIndex(-1, region); if (ip>=0) { removeParticle(ip); q = 1; } } return q; } private int setPotentialP(double pot, int region[]) { // return charge changed int ip,q; double p; p = potentialOf(region); q = 0; if (p>1.02*pot) { ip = removableParticleIndex( 1, region); if (ip>=0) { removeParticle(ip); q = -1; } } else if (p<0.98*pot) { ip = putParticle( 1, region); if (ip>=0) q = 1; } return q; } // current source private int currentSource(double pp, int source[], int sink[]) { // return charge changed int rn,rp,q; q = 0; if (pp>=0.0 && Math.random()=0 && rp>=0) { removeParticle(rn); removeParticle(rp); q = -1; } } return q; } // private int putParticle(int knd, int region[]) { // return particle index int n,nxy,i,ir; int ix,iy,iz, xPos,yPos,zPos, xSize,ySize,zSize; xPos = region[0]; yPos = region[1]; zPos = region[2]; xSize = region[3]; ySize = region[4]; zSize = region[5]; n = xSize*ySize*zSize; nxy = xSize*ySize; if (n<=0) return -1; if (knd!=-1 && knd!=1) return -1; ir = (int)(n*Math.random()); for (i=0; i=NNx || iy<0 || iy>=NNy || iz<0 || iz>=NNz) return -1; if (knd!=1 && knd!=-1) return -1; if (field[ix][iy][iz]!=0) return -1; idx = searchIndex(); if (idx==-1) return -1; field[ix][iy][iz] = (byte)knd; kind[idx] = (byte)knd; px[idx] = ix; py[idx] = iy; pz[idx] = iz; return idx; } private int searchIndex() { int i; for (i=0; i