/** applet No. 1149 * * smoothed sand - discrete element method 3D * - multi thread DEM3D :: display - asynchronous * * Created by Ikeuchi Mitsuru on April 01 2007. * Copyright (c) 2007 Ikeuchi Mitsuru. All rights reserved. * * ver 0.0.1 2007.04.01 created * ver 0.0.2 2007.06.18 improved code * */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class smoothedSandMtDEM3D extends Applet implements MouseListener, MouseMotionListener, ItemListener, ActionListener, AdjustmentListener, Runnable { // ------------------------------------ preset field ----------- Thread th = null; // for run()-paint() thread Dynamics3D d3d = null; DisplayD3D dsp = new DisplayD3D(); // for event Choice ch_mat,ch_view; Button bt_reset, bt_startStop, bt_step; Scrollbar sc_gravity, sc_depth, sc_scale; // for off-paint buffer Dimension dim; Image imgOff; Graphics gOff; int dgX, dgY, dgXb,dgYb; // mouse int sleepTime = 50; 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("line"); ch_view.add("ball+line"); ch_view.add("velocity"); ch_view.addItemListener(this); ch_view.select("ball+line"); 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_gravity = new Scrollbar(Scrollbar.HORIZONTAL,98,10,0,510); sc_gravity.addAdjustmentListener(this); sc_depth = new Scrollbar(Scrollbar.HORIZONTAL,50,10,0,110); sc_depth.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(new Label(" ")); pnl.add(sc_gravity); pnl.add(sc_depth); pnl.add(ch_view); add(pnl,"North"); } public void start() { if (d3d == null) { d3d = new Dynamics3D(); d3d.start(); } if (th == null) { th = new Thread(this); th.start(); } } public void stop() { if (th != null) th = null; if (d3d != null) d3d = null; } // ---------------------------------- event listener ----------- public void itemStateChanged(ItemEvent ev){ if (ev.getSource() == ch_mat){ //MAT1 = ch_mat.getSelectedIndex(); } else if (ev.getSource() == ch_view){ dispMode = ch_view.getSelectedIndex(); } } public void actionPerformed(ActionEvent ev){ if(ev.getSource() == bt_reset){ d3d.reset(); thCount = 0; } else if (ev.getSource() == bt_startStop){ if (d3d.getStartSW()==0) { d3d.setStartSW(1); } else { d3d.setStartSW(0); } } else if (ev.getSource() == bt_step){ if (d3d.getStartSW()==0) { d3d.setStepSW(); } } } public void adjustmentValueChanged(AdjustmentEvent ev){ if (ev.getSource() == sc_gravity) { d3d.setGravity( 0.1*(double)(sc_gravity.getValue()) ); } else if (ev.getSource() == sc_depth) { dsp.setDepth( 0.01*(double)(sc_depth.getValue()) ); } else if (ev.getSource() == sc_scale) { dsp.setViewScale( 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 (d3d != null) { dsp.plotGraph(gOff, d3d, dispMode, thCount); } } } // ================================= display D3D class =========== class DisplayD3D { Graphics gOff; Dynamics3D d3d; private int Nmt; private double xMax = Dynamics3D.xMax; private double yMax = Dynamics3D.yMax; private double zMax = Dynamics3D.zMax; private double AU = Dynamics3D.AU; private double AA = Dynamics3D.AA; private double zDepth = xMax; private double dispWidth = 250.0; private double dispScale = (dispWidth/xMax); private double viewScale = 1.0; private double depth = 0.5; private double cx = 0.5*xMax; private double cy = 0.5*yMax; private double cz = 0.5*zMax; private double theta = -20.0*3.14/180.0; private double fai = 10.0*3.14/180.0; private int NN = 10000; private int srtz[][] = new int[2][NN]; private double px[] = new double[NN]; private double py[] = new double[NN]; private double pz[] = new double[NN]; private double wkx[] = new double[8]; private double wky[] = new double[8]; private double wkz[] = new double[8]; private double pwkx[] = new double[8]; private double pwky[] = new double[8]; private double pwkz[] = new double[8]; private int boxp[][] = { {0,1},{0,2},{0,4},{1,3},{1,5},{2,3},{2,6},{4,5},{4,6},{3,7},{5,7},{6,7} }; private int drawnCount = 0; // ------------------------------- class constructor ----------- DisplayD3D() { setWaku(); } // ----------------------------------- class methods ----------- public void plotGraph(Graphics gg, Dynamics3D ad3d, int dispMode, int thCount) { int d3dCount, gbx, gby, gx; gOff = gg; d3d = ad3d; if (d3d==null) return; d3dCount = d3d.getCount(); if (d3dCount==drawnCount) return; drawnCount = d3dCount; Nmt = d3d.getNmt(); gOff.setColor(Color.white); gOff.fillRect(0,0,630,420); rotate(theta,fai); zSort(); gbx = 70; gby = 90; if (dispMode==0) { ballPlot(gbx,gby, 1.2, 0); } else if (dispMode==1) { ballPlot(gbx,gby, 0.5, 1); } else if (dispMode==2) { ballPlot(gbx,gby, 0.5, 2); } else if (dispMode==3) { velocity3DPlot(gbx,gby, 20.0,0); } else if (dispMode==4) { ; } else if (dispMode==5) { ; } gbx = 630/6; gOff.setColor(Color.black); gOff.drawString("t="+(int)(d3d.getTime()*10000.0+0.5)/10.0+" ms",gbx*0+10,40); if (d3d.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("gravity="+(int)(d3d.getGravity()/9.8*100.0+0.5)/100.0+" g",gbx*3+10,40); gOff.drawString("depth="+(int)(depth*100.0+0.5)+"%",gbx*4+10,40); gOff.drawString("view",gbx*5+10,40); gx = 450; gOff.setColor(Color.black); gOff.drawString("Box="+(int)(xMax*1000.0+0.5)/10.0+" x "+(int)(yMax*1000.0+0.5)/10.0+" x "+(int)(zMax*1000.0+0.5)/10.0+" cm",gx,60); gOff.drawString("regMax="+d3d.regMax()+"",530,80); gOff.drawString("secMax="+d3d.secMax()+"",530,100); gOff.setColor(Color.black); gOff.drawString("thread D3D = "+d3d.getCount()+" ",20,400); gOff.drawString("thread disp = "+thCount+" ",220,400); } // ------------------------------------ plot methods ----------- private void ballPlot(int gbx, int gby, double size, int imode) { int i,j,k,jj,gx,gy,g2x,g2y,gr; double sz,scl,tm,r,r0,col; drawWaku(gbx,gby,0); scl = dispScale*viewScale; sz = size*viewScale/AA; for (i=0; idepth) continue; gx = (int)(scl*px[j])+gbx; gy = (int)(scl*py[j])+gby; gr = (int)(sz*d3d.getDia(j)*(0.3*(pz[j]/zDepth)+0.7)); if (gr<2) gr = 2; if (imode==1 || imode==2) { for (k=1; k0.66) col = 0.66; gOff.setColor(Color.getHSBColor((float)(col),0.5f,0.8f)); } else { gOff.setColor(Color.gray); } gOff.drawLine(gx,gy, g2x, g2y); } } } if (imode==0 || imode==2) { gOff.setColor(Color.getHSBColor( d3d.getCol(j),0.8f,(float)(0.4*pz[j]/zDepth+0.3))); gOff.fillOval(gx-gr/2,gy-gr/2, gr, gr); } } drawWaku(gbx,gby,1); } private void velocity3DPlot(int gbx, int gby, double mag, int imode) { int i,j,gx,gy,g2x,g2y,gr; double sc,sz,m,p2x,p2y,p2z,rotp2x,rotp2y,rotp2z,dt; double cosTh,sinTh,cosFi,sinFi; dt = d3d.getdt(); drawWaku(gbx,gby,0); cosTh = Math.cos(theta); sinTh = Math.sin(theta); cosFi = Math.cos(fai); sinFi = Math.sin(fai); sc = dispScale*viewScale; sz = 0.3*viewScale/AA; for (i=0; i0) { gOff.setColor(Color.blue); } else { gOff.setColor(Color.red); } gOff.drawLine(gx,gy, g2x,g2y); gOff.setColor(Color.getHSBColor( d3d.getCol(j),0.8f,(float)(0.4*pz[j]/zDepth+0.3))); gOff.fillOval(gx-gr/2,gy-gr/2, gr, gr); } drawWaku(gbx,gby,1); } private void drawWaku(int gbx, int gby, int imode) { int i,gx,gy,g2x,g2y,farPoint; double sc,tmp; sc = dispScale*viewScale; farPoint = findMin(); for (i=0; i<12; i++) { gx = (int)(sc*pwkx[boxp[i][0]])+gbx; gy = (int)(sc*pwky[boxp[i][0]])+gby; g2x = (int)(sc*pwkx[boxp[i][1]])+gbx; g2y = (int)(sc*pwky[boxp[i][1]])+gby; if (imode==0) { if (boxp[i][0]==farPoint || boxp[i][1]==farPoint) { gOff.setColor(Color.lightGray); gOff.drawLine(gx,gy, g2x, g2y); } } else if (imode==1) { if (boxp[i][0]!=farPoint && boxp[i][1]!=farPoint) { gOff.setColor(Color.black); gOff.drawLine(gx,gy, g2x, g2y); } } } } private int findMin() { int i,im; double m; im = 0; m = pwkz[im]; for (i=0; i<8; i++) { if (pwkz[i]=srtz[1][p]) p = i; k = qSortPartition(i,j,srtz[1][p]); qSort(i,k-1); qSort(k,j); } } private int qSortPartition(int i,int j, int x) { int l,r,w; l = i; r = j; while (l<=r) { while (l<=j && srtz[1][l]=i && srtz[1][r]>=x) r--; if (l>r) break; w = srtz[0][l]; srtz[0][l] = srtz[0][r]; srtz[0][r] = w; w = srtz[1][l]; srtz[1][l] = srtz[1][r]; srtz[1][r] = w; l++; r--; } return ( l ); } // rotate private void rotate(double th,double fi) { int i; double cosTh,sinTh,cosFi,sinFi,x,y,z; cosTh = Math.cos(th); sinTh = Math.sin(th); cosFi = Math.cos(fi); sinFi = Math.sin(fi); for (i=0; i0) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } } // --------------------------- set initial condition ----------- private void setInitialCondition() { int i; double s; setForceTable(); t = 0.0; count = 0; i = 0; i = setCloud(i, 2); i = setFloor(i, 0.7*yMax, 0); Nmt = i; //setBond(); } private int setCloud(int ii, int mat) { int i,ix,iy,iz,nx,ny,nz; double a; i = ii; a = 1.4*material[mat][4]; nx = (int)(xMax/a); ny = (int)(0.6*yMax/a); nz = (int)(zMax/a); for (ix=0; ix8.0*a*a) { kind[i] = mat; xx[i] = ax*(ix+0.5); yy[i] = yPos; zz[i] = az*(iz+0.5); vx[i] = 0.0; vy[i] = 0.0; vz[i] = 0.0; ffx[i] = 0.0; ffy[i] = 0.0; ffz[i] = 0.0; i += 1; } } } return ( i ); } // set forceTable[i][j][ir] private void setForceTable(){ int i,j,ir; double d,a,r0,y,r,sc; for (i=0; i=0.8*rc && r0) { a2 = dtv2/material[kind[i]][0]; vx[i] += a2*ffx[i]; vy[i] += a2*ffy[i]; vz[i] += a2*ffz[i]; xx[i] += vx[i]*dt; yy[i] += vy[i]*dt; zz[i] += vz[i]*dt; } } forceCalc(); for (i=0; i0) { a2 = dtv2/material[kind[i]][0]; vx[i] += a2*ffx[i]; vy[i] += a2*ffy[i]; vz[i] += a2*ffz[i]; } } setBoundary(); } private void forceCalc() { int i,j,k,ki,kj; double xij,yij,zij,r2,rij,f,fxij,fyij,fzij; for(i=0;ii) { xij = xx[i]-xx[j]; yij = yy[i]-yy[j]; zij = zz[i]-zz[j]; r2 = xij*xij + yij*yij + zij*zij; rij = Math.sqrt(r2); ki = kind[i]; kj = kind[j]; f = -100000000.0*(material[ki][2]+material[kj][2])*(rij-0.5*(material[ki][4]+material[kj][4])); fxij = f*xij/rij; fyij = f*yij/rij; fzij = f*zij/rij; ffx[i] += fxij; ffy[i] += fyij; ffz[i] += fzij; ffx[j] += -fxij; ffy[j] += -fyij; ffz[j] += -fzij; } } } } private double force(double r, int ki, int kj) { int i; double a,ret; i = (int)(r/hh); a = r - i*hh; ret = ((hh-a)*forceTable[ki][kj][i] + a*forceTable[ki][kj][i+1])/hh; return( ret ); } private void setBoundary() { int i; double rr; rr = 0.9; for (i=0; i xMax) { xx[i] = xMax; vx[i] = -rr*vx[i]; vy[i] = rr*vy[i]; vz[i] = rr*vz[i]; } if (yy[i] < 0.0) { yy[i] = 0.0; vx[i] = rr*vx[i]; vy[i] = -rr*vy[i]; vz[i] = rr*vz[i]; } if (yy[i] > yMax) { yy[i] = yMax; vx[i] = rr*vx[i]; vy[i] = -rr*vy[i]; vz[i] = rr*vz[i]; } if (zz[i] < 0.0) { zz[i] = 0.0; vx[i] = rr*vx[i]; vy[i] = rr*vy[i]; vz[i] = -rr*vz[i]; } if (zz[i] > zMax) { zz[i] = zMax; vx[i] = rr*vx[i]; vy[i] = rr*vy[i]; vz[i] = -rr*vz[i]; } } } // registration private void registration() { int i,j,k,ip,jp,kp,i0,i1,j0,j1,k0,k1,iq; double r2,rreg,rreg2; double x,y,z; preRegistration(); rreg = rc + 1.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; k0 = (int)(Nsz*(zz[ip]-rreg)/zMax); if (k0<0) k0 = 0; k1 = (int)(Nsz*(zz[ip]+rreg)/zMax); if (k1>=Nsz) k1 = Nsz-1; for(i=i0;i<=i1;i++) { for(j=j0;j<=j1;j++) { for(k=k0;k<=k1;k++) { for(iq=1;iq<=section[i][j][k][0];iq++) { jp = section[i][j][k][iq]; if (jp>ip) { r2=(xx[ip]-xx[jp])*(xx[ip]-xx[jp])+(yy[ip]-yy[jp])*(yy[ip]-yy[jp])+(zz[ip]-zz[jp])*(zz[ip]-zz[jp]); if (r2=Nsx) i = Nsx-1; j = (int)(Nsy*yy[ip]/yMax); if (j>=Nsy) j = Nsy-1; k = (int)(Nsz*zz[ip]/zMax); if (k>=Nsz) k = Nsz-1; iq = section[i][j][k][0]+1; section[i][j][k][0] = iq; section[i][j][k][iq] = ip; } } // ----------------------------------------- utility ----------- // bond manager private void clearBond() { int i,j,ip; double r,r0; for (i=0; im) { m = reg[i][0]; } } return(m); } public int secMax() { int i,j,k,m; m = 0; for(i=0;im) { m = section[i][j][k][0]; } } } } return(m); } // ------------------------------------- I/O methods ----------- // control public void reset() { resetSW = 1; } public void setStartSW(int sw) { startSW = sw; } public int getStartSW() { return startSW; } public void setStepSW() { stepSW = 1; } public int getCount() { return count; } public void setGravity(double g) { gravity = g; } public double getGravity() { return gravity; } public void setSpin(double s) { spin = s; } public double getSpin() { return spin; } // get data public double getTime() { return t; } public double getdt() { return dt; } public int getNmt() { return Nmt; } public double getxx(int i) { return xx[i]; } public double getyy(int i) { return yy[i]; } public double getzz(int i) { return zz[i]; } public double getvx(int i) { return vx[i]; } public double getvy(int i) { return vy[i]; } public double getvz(int i) { return vz[i]; } public double getMass(int i) { return material[kind[i]][0]; } //public double getPotentialD(int i) { return material[kind[i]][2]; } //public double getPotentialA(int i) { return material[kind[i]][3]; } public double getDia(int i) { return material[kind[i]][4]; } public double getDia(int i, int j) { return 0.5*(material[kind[i]][4]+material[kind[j]][4]); } public float getCol(int i) { return (float)material[kind[i]][6]; } public int getReg(int i, int j) { return reg[i][j]; } }