/** applet No. 1077 * * breakthrough - dynamics 2D * - multi thread D2D :: display - asynchronous * - Hash table * * Created by Ikeuchi Mitsuru on December 16 2006. * Copyright (c) 2006-2007 Ikeuchi Mitsuru. All rights reserved. * * ver 0.0.1 2006.12.16 created * ver 0.0.2 2007.06.09 improved code * */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class HashTableMtD2D extends Applet implements MouseListener, MouseMotionListener, ItemListener, ActionListener, AdjustmentListener, Runnable { // ------------------------------------ preset field ----------- Thread th = null; // for run()-paint() thread Dynamics2D d2d = null; DisplayD2D dsp = new DisplayD2D(); // for event Choice ch_mat,ch_view; Button bt_reset, bt_startStop, bt_step, bt_go; Scrollbar sc_gravity, sc_vx0, sc_spin, sc_scale; // for off-paint buffer Dimension dim; Image imgOff; Graphics gOff; int dgX, dgY, dgXb, dgYb; int sleepTime = 30; int dispMode = 2; int thCount = 0; // ------------------------------ applet main thread ----------- public void init() { resize(630,420); setBackground(Color.white); dim = getSize(); imgOff = createImage(dim.width,dim.height); gOff = imgOff.getGraphics(); ch_mat = new Choice(); ch_mat.add("fixed"); ch_mat.add("A"); ch_mat.add("B"); ch_mat.add("C"); ch_mat.addItemListener(this); ch_mat.select("B"); ch_view = new Choice(); ch_view.add("ball"); ch_view.add("bond"); ch_view.add("ball+bond"); ch_view.add("velocity"); ch_view.add("force"); ch_view.addItemListener(this); ch_view.select("ball+bond"); 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); bt_go = new Button("go"); bt_go.addActionListener(this); sc_gravity= new Scrollbar(Scrollbar.HORIZONTAL,98,10,0,510); sc_gravity.addAdjustmentListener(this); sc_vx0= new Scrollbar(Scrollbar.HORIZONTAL,40,10,0,80); sc_vx0.addAdjustmentListener(this); sc_spin= new Scrollbar(Scrollbar.HORIZONTAL,300,10,0,410); sc_spin.addAdjustmentListener(this); sc_scale= new Scrollbar(Scrollbar.HORIZONTAL,100,10,50,210); sc_scale.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(sc_vx0); pnl.add(bt_go); pnl.add(sc_scale); pnl.add(ch_view); add(pnl,"North"); } public void start() { if (d2d == null) { d2d = new Dynamics2D(); d2d.start(); } if (th == null) { th = new Thread(this); th.start(); } } public void stop() { if (th != null) th = null; if (d2d != null) d2d = null; } // ---------------------------------- event listener ----------- public void itemStateChanged(ItemEvent ev){ if (ev.getSource() == ch_view){ dispMode = ch_view.getSelectedIndex(); } } public void actionPerformed(ActionEvent ev){ if(ev.getSource() == bt_reset){ d2d.reset(); thCount = 0; } else if (ev.getSource() == bt_startStop){ if (d2d.getStartSW()==0) { d2d.setStartSW(1); } else { d2d.setStartSW(0); } } else if (ev.getSource() == bt_step){ if (d2d.getStartSW()==0) { d2d.setStepSW(); } } else if (ev.getSource() == bt_go){ d2d.setGo(); } } public void adjustmentValueChanged(AdjustmentEvent ev){ if (ev.getSource() == sc_gravity) { d2d.setGravity( 0.1*(double)(sc_gravity.getValue()) ); } else if (ev.getSource() == sc_vx0) { d2d.setvx0( 0.1*(double)(sc_vx0.getValue()) ); } else if (ev.getSource() == sc_spin) { d2d.setSpin( 0.01*(double)(sc_spin.getValue()) ); } else if (ev.getSource() == sc_scale) { dsp.setScale( 0.01*(double)(sc_scale.getValue()) ); } } 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; } dsp.setViewDelta( (dgX-dgXb), (dgY-dgYb) ); } // ========================= 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); } private void offPaint() { if (d2d != null) { dsp.plotGraph(gOff, d2d, dispMode, thCount); } } } // ================================= display D2D class =========== class DisplayD2D { Graphics gOff; Dynamics2D d2d; private double xMax = Dynamics2D.xMax; private double yMax = Dynamics2D.yMax; private int Nmt = 0; private double dispWidth = 500.0; private double dispScale = (dispWidth/xMax); private double viewScale = 1.0; private double xShift = 0.0; private double yShift = 0.0; private int drawnCount = 0; DisplayD2D() { } public void plotGraph(Graphics gg, Dynamics2D ad2d, int dispMode, int thCount) { int d2dCount, gx, gy, gbx; double sc; gOff = gg; d2d = ad2d; if (d2d==null) return; d2dCount = d2d.getCount(); if (d2dCount==drawnCount) return; drawnCount = d2dCount; Nmt = d2d.getNmt(); sc = dispScale*viewScale; gx = 30+(int)(sc*xShift); gy = 100+(int)(sc*yShift); gOff.setColor(Color.white); gOff.fillRect(0,0,630,420); drawWaku(gOff,gx,gy,sc, viewScale); if (dispMode==0) { ballPlot(gOff,gx,gy,sc, 0.8, 0.9); } else if (dispMode==1) { bondPlot(gOff,gx,gy,sc); } else if (dispMode==2) { ballPlot(gOff,gx,gy,sc, 0.4, 0.9); bondPlot(gOff,gx,gy,sc); } else if (dispMode==3) { ballPlot(gOff,gx,gy,sc, 0.4, 0.9); velocityPlot(gOff,gx,gy,sc,viewScale*20.0); } else if (dispMode==4) { ballPlot(gOff,gx,gy,sc, 0.4, 0.9); forcePlot(gOff,gx,gy,sc,viewScale*1.0); } else if (dispMode==5) { ; } gbx = 630/6; gOff.setColor(Color.black); gOff.drawString("t="+(int)(d2d.getTime()*10000.0+0.5)/10.0+" ms",gbx*0+10,40); if (d2d.getStartSW()==1) { gOff.drawString("started",630/6*1+10,40); } else { gOff.drawString("stop",630/6*1+10,40); } gOff.setColor(Color.black); gOff.drawString("vx0="+(int)(d2d.getvx0()*100.0+0.5)/100.0+" m/s",gbx*2+10,40); //gOff.drawString("spin0="+(int)(spin*100.0+0.5)/100.0+" m/s",gbx*2+10,40); //gOff.drawString("gravity="+(int)(gravity/9.8*100.0+0.5)/100.0+" g",gbx*3+10,40); gOff.drawString("scale="+(int)(viewScale*100.0+0.5)+"%",gbx*4+10,40); gOff.drawString("view",gbx*5+10,40); gOff.setColor(Color.black); gOff.drawString("Box="+(int)(xMax*1000.0+0.5)/10.0+" x "+(int)(yMax*1000.0+0.5)/10.0+" cm",430,60); } private void ballPlot(Graphics gOff, int gx, int gy, double sc, double dmag, double dens) { int i,ix,iy,ir; double tm; for (i=0; ii) { if (d2d.bondQ(i,j)==-1) { col = 0.33-20.0*(rbond2-1.0); if (col<0.01) col = 0.01; if (col>0.99) col = 0.99; gOff.setColor(Color.getHSBColor((float)col,0.9f,0.9f)); ix2 = (int)(sc*xj)+gx; iy2 = (int)(sc*yj)+gy; gOff.drawLine(ix,iy, ix2,iy2); } else if (rbond2<1.1) { gOff.setColor(Color.gray); ix2 = (int)(sc*xj)+gx; iy2 = (int)(sc*yj)+gy; gOff.drawLine(ix,iy, ix2,iy2); } } } } } private void velocityPlot(Graphics gOff, int gx, int gy, double sc, double vmag) { int i,ix,iy,ir,ix2,iy2; double vx; for (i=0; i0) { gOff.setColor(Color.blue); } else { gOff.setColor(Color.red); } gOff.drawLine(ix,iy, ix2,iy2); } } private void forcePlot(Graphics gOff, int gx, int gy, double sc, double fmag) { int i,ix,iy,ir,ix2,iy2; double ffx; for (i=0; i0) { gOff.setColor(Color.blue); } else { gOff.setColor(Color.red); } gOff.drawLine(ix,iy, ix2,iy2); } } private void drawWaku(Graphics gOff, int gx, int gy, double sc, double viewScale) { int ix,iy,gball,idx,idy; gball = (int)(3.0*viewScale); gOff.setColor(Color.black); ix = (int)(sc*xMax); iy = (int)(sc*yMax); idx = ix+2*gball; idy = iy+2*gball; gOff.drawRect(gx-gball,gy-gball,idx,idy); } // ------------------------------------- I/O methods ----------- public void setViewDelta(double xDisplacement, double yDisplacement) { xShift += (1.0/viewScale/dispScale)*xDisplacement; yShift += (1.0/viewScale/dispScale)*yDisplacement; } public void setScale(double sc) { viewScale = sc; } } // ================================= dynamics 2D class =========== class Dynamics2D extends Thread { private double t = 0.0; private double dt = 2.0e-5; public static final double xMax = 100.0*0.01; // m public static final double yMax = 50.0*0.01; // m private int Nmt = 10000; private int Nsx = 100; private int Nsy = 50; private double gravity = 0.0; // m/s2 private double spin = 3.0; private int incRate = 20; private double vx0 = 4.0; private double rc = 0.01; // cutoff=1cm private double rc2 = rc*rc; private double hh = rc/1000.0; // delta x private double AU = 1.0e-3; private double EE = 0.01; private double AA = 0.001; private double material[][] = { // 0:mass(AU) 1:charge 2:D(EE) 3:A(/AA) 4:r0(AA) 5:damp 6:color { 10.0 *AU, 0.0*EE, 0.1*EE, 2.0/AA, 8.0*AA, 1.0, 0.85 }, // fixed ball { 5.0 *AU, 0.0*EE, 2.0*EE, 2.0/AA, 8.0*AA, 0.1, 0.05 }, // 1 A { 5.0 *AU, 0.0*EE, 5.0*EE, 2.0/AA, 8.0*AA, 0.1, 0.15 }, // 2 B { 10.0 *AU, 0.0*EE, 8.0*EE, 2.0/AA, 8.0*AA, 1.0, 0.25 } // 3 C }; private String materialStr[] = { "fixed" ,"A" ,"B","C" }; private int NmatKind = 4; private int NN = Nmt + 1; private int kind[] = new int[NN]; private double xx[] = new double[NN]; private double yy[] = new double[NN]; private double vx[] = new double[NN]; private double vy[] = new double[NN]; private double ffx[] = new double[NN]; private double ffy[] = new double[NN]; private int bond[][] = new int[NN][10]; private int regReadyFlag = 0; private int Nhash = NN*5; private int hashedSec[] = new int[Nhash]; private int Nreg = NN*10; private int hashedReg[] = new int[Nreg]; private double forceTable[][][] = new double[NmatKind][NmatKind][1020]; private int resetSW = 0; private int startSW = 1; private int stepSW = 0; private int goSW = 0; private int sleepTime = 1; private int stopSleepTime = 100; private int count = 0; // ------------------------------- class constructor ----------- Dynamics2D() { 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; double s; setForceTable(); t = 0.0; count = 0; goSW = 0; i = 0; i = setBall(i, 7.0*0.01, 0.5*yMax,2); i = setWall(i, 0.5*xMax, 5, 1); Nmt = i; setBond(); } int setBall(int ii, double xpos, double ypos,int mat) { int i,ix,iy,iz,ir2; double a,r2,r02,x,y; i = ii; a = material[mat][4]; r02 = 13.0*a*a; for (ix=-4; ix<=4; ix++) { for (iy=-4; iy<=4; iy++) { kind[i] = mat; x = a*ix+0.5*a*((iy+10)%2); y = 0.866*a*iy; r2 = x*x+y*y; if (r2=0.8*rc && r0) { a2 = dtv2/material[kind[i]][0]; vx[i] += a2*ffx[i]; vy[i] += a2*ffy[i]; xx[i] += vx[i]*dt; yy[i] += vy[i]*dt; } } forceCalc(); for (i=0; i0) { a2 = dtv2/material[kind[i]][0]; vx[i] += a2*ffx[i]; vy[i] += a2*ffy[i]; } } setBoundary(); } private void forceCalc() { int i,j,k,ih; double xi,xj,yi,yj; double r2,rij,f,fxij,fyij; for(i=0;i xMax) { xx[i] = xMax; vx[i] = -rr*vx[i]; vy[i] = rr*vy[i]; } if (yy[i] < 0.0) { yy[i] = 0.0; vx[i] = rr*vx[i]; vy[i] = -rr*vy[i]; } if (yy[i] > yMax) { yy[i] = yMax; vx[i] = rr*vx[i]; vy[i] = -rr*vy[i]; } } } // Hash table manager private void registration() { int i,j,ip,ii,jp,kp,i0,i1,j0,j1,ih; double r2,rreg,rreg2; setHashedSec(); regReadyFlag = 0; initHashedReg(); rreg = rc + 5.0*incRate*dt; rreg2 = rreg*rreg; for(ip=0;ip=Nsx) i1 = Nsx-1; j0 = (int)(Nsy*(yy[ip]-rreg)/yMax); if (j0<0) j0 = 0; j1 = (int)(Nsy*(yy[ip]+rreg)/yMax); if (j1>=Nsy) j1 = Nsy-1; for(i=i0;i<=i1;i++) { for(j=j0;j<=j1;j++) { ih = hash(i,j); for(ii=ih;iiip) { r2=(xx[ip]-xx[jp])*(xx[ip]-xx[jp])+(yy[ip]-yy[jp])*(yy[ip]-yy[jp]); if (r2=Nsx) ix = Nsx-1; iy = (int)(Nsy*yy[ip]/yMax); if (iy>=Nsy) iy = Nsy-1; ih = hash(ix,iy); for(i=ih;i