/** applet No. 773 * * water tank sloshing * - smoothed particle hydrodynamics 2D * * Created by Ikeuchi Mitsuru on August 06 2005. * Copyright (c) 2005 Ikeuchi Mitsuru. All rights reserved. * * ver 0.0.1 2005.08.06 created * ver 0.0.2 2006.11.19 sc_vx0 bug fixed * */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class sloshingSPH2D extends Applet implements MouseListener, MouseMotionListener, ItemListener, ActionListener, AdjustmentListener, Runnable { /* -------------------------------------- set global ------ */ Button bt_reset, bt_startStop, bt_go; Choice ch_view; Scrollbar sc_vx0, sc_xWidth, sc_alpha, sc_dispScale; Thread th = null; Dimension dim; Image imgOff; Graphics gOff; int sleepTime = 30; int dispMode =4; int incRate = 10; int resetSW = 0; int started = 1; double dispScale = 1.0; double scale = 20.0; double alpha = 0.05; double thermalDiffusivity = 1.5e-7; /* m2/s */ double dens0 = 1000.0; /* kg/m3 */ double vx0 = 5.0; /* m/s */ double tPulse = 0.1; /* s */ double pulseWidth = 0.1; /* s */ double xWidth = 1.0; double vxTank = vx0; int dgX, dgY, dgXb, dgYb; double xShift = 0.0; double yShift = 0.0; double xMax = 25.0; /* m */ double yMax = 15.0; /* m */ double t = 0.0; double dt = 0.001; double hh0 = 0.25; double rBond = hh0*1.2; int NNp = 5000; int kind[] = new int [NNp]; int bond[][] = new int[NNp][8]; double xx[] = new double [NNp]; double yy[] = new double [NNp]; double vx[] = new double [NNp]; double vy[] = new double [NNp]; double ax[] = new double [NNp]; double ay[] = new double [NNp]; double hh[] = new double [NNp]; double mass[] = new double [NNp]; double cp[] = new double [NNp]; double density[] = new double [NNp]; double pressure[] = new double [NNp]; double energy[] = new double [NNp]; double power[] = new double [NNp]; int Nsx = 50; int Nsy = 30; int section[][][] = new int[Nsx][Nsy][50]; /* ----------------------------- applet control ------ */ public void init() { resize(630,420); setBackground(Color.white); dim = getSize(); imgOff = createImage(dim.width,dim.height); gOff = imgOff.getGraphics(); bt_reset= new Button("reset"); bt_reset.addActionListener(this); bt_startStop= new Button("start/stop"); bt_startStop.addActionListener(this); bt_go = new Button("shake"); bt_go.addActionListener(this); ch_view = new Choice(); ch_view.addItem("particle"); ch_view.addItem("velocity"); ch_view.addItem("density"); ch_view.addItem("temperature"); ch_view.addItem("pressure"); ch_view.addItemListener(this); ch_view.select("pressure"); sc_vx0= new Scrollbar(Scrollbar.HORIZONTAL,50,10,1,310); sc_vx0.addAdjustmentListener(this); sc_xWidth= new Scrollbar(Scrollbar.HORIZONTAL,100,10,1,210); sc_xWidth.addAdjustmentListener(this); sc_alpha= new Scrollbar(Scrollbar.HORIZONTAL,5,10,1,110); sc_alpha.addAdjustmentListener(this); sc_dispScale= new Scrollbar(Scrollbar.HORIZONTAL,100,10,50,210); sc_dispScale.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_go); pnl.add(sc_vx0); pnl.add(sc_xWidth); pnl.add(ch_view); add(pnl,"North"); setInitialCondition(); } public void start() { if (th == null) { th = new Thread(this); th.start(); } } public void stop() { if (th != null) { th.stop(); th = null; } } public void itemStateChanged(ItemEvent ev){ if (ev.getSource() == ch_view) { dispMode = ch_view.getSelectedIndex(); } } public void actionPerformed(ActionEvent ev){ if (ev.getSource() == bt_reset){ t = 0.0; resetSW = 1; started = 0; } else if (ev.getSource() == bt_startStop){ if (started==0) { started = 1; } else { started = 0; } } else if (ev.getSource() == bt_go){ gogogo(); } } public void adjustmentValueChanged(AdjustmentEvent ev){ if (ev.getSource() == sc_vx0) { vx0 = 0.1*sc_vx0.getValue(); } else if (ev.getSource() == sc_xWidth) { xWidth = 0.01*sc_xWidth.getValue(); } else if (ev.getSource() == sc_alpha) { alpha = 0.01*sc_alpha.getValue(); } else if (ev.getSource() == sc_dispScale) { dispScale = 0.01*sc_dispScale.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; } xShift += (1.0/scale/dispScale)*(dgX-dgXb); yShift += (1.0/scale/dispScale)*(dgY-dgYb); } public void run() { while (th != null) { try { timeEvolution(); offPaint(); repaint(); Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { g.drawImage(imgOff,0,0,this); } /* ----------------------------- offPaint -------------------- */ void offPaint() { int gb,gbx,gby; double sc; gOff.setColor(Color.white); gOff.fillRect(0,0,dim.width,dim.height); sc = scale*dispScale; gbx = 30+(int)(sc*xShift); gby = 80+(int)(sc*yShift); gOff.setColor(Color.black); gOff.drawRect(gbx,gby,(int)(sc*xMax+0.5),(int)(sc*yMax+0.5)); if (dispMode==0) { ovalPlot(gbx,gby,sc); } else if (dispMode==1) { linePlot(gbx,gby,sc,5.0); } else if (dispMode==2) { fieldPlot(gbx,gby,sc,density,0.0002); } else if (dispMode==3) { tempPlot(gbx,gby,sc,298.0,1.0/10.0); } else if (dispMode==4) { fieldPlot(gbx,gby,sc,pressure,0.000005); } gOff.setColor(Color.black); gOff.drawString("t="+(int)(t*100.0+0.5)/100.0+" s",630/6*0+10,40); if (started==1) { gOff.drawString("started",630/6*1+10,40); } else { gOff.drawString("stopped",630/6*1+10,40); } gOff.drawString("vx0="+(int)(vx0*10.0)/10.0+" m/s",630/6*3+10,40); gOff.drawString("xWidth="+(int)(xWidth*100.0)/100.0+" m",630/6*4+10,40); gOff.drawString("view",630/6*5+10,40); gOff.drawString("maxSec="+maxSection()+" ",10,60); gOff.drawString("Lx=25m, Ly=15m, water tank(x=11m) sloshing",200,60); } /*------------------------- plot methods -------------------*/ void ovalPlot(int gx, int gy, double sc) { int i,j,ir; ir = (int)(0.5*sc+0.5); gOff.setColor(Color.blue); for (i=0; i0) { gOff.setColor(Color.blue); } else if (kind[i]==0) { gOff.setColor(Color.green); } else { gOff.setColor(Color.orange); } gOff.drawOval(gx+(int)(xx[i]*sc+0.5)-ir/2,gy+(int)(yy[i]*sc+0.5)-ir/2, ir, ir); } gOff.setColor(Color.red); for (i=0; i0.0) { gOff.setColor(Color.getHSBColor(0.66f,0.8f,0.8f)); } else { gOff.setColor(Color.getHSBColor(0.01f,0.8f,0.8f)); } gOff.drawLine(ix,iy,ix+(int)(vx[i]*dispScale*mag+0.5),iy+(int)(vy[i]*dispScale*mag+0.5)); if (kind[i]<0) { gOff.setColor(Color.orange); gOff.drawOval(ix-ir/2,iy-ir/2, ir, ir); } else if (kind[i]==0) { gOff.setColor(Color.green); gOff.drawOval(ix-ir/2,iy-ir/2, ir, ir); } } } void fieldPlot(int gx, int gy, double sc, double field[], double mag) { int i,j,ir; double c; ir = (int)(0.5*sc+0.5); for (i=0; i1.0) c = 1.0; gOff.setColor(Color.getHSBColor((float)(0.66-0.66*c),0.8f,0.8f)); gOff.drawOval(gx+(int)(xx[i]*sc+0.5)-ir/2,gy+(int)(yy[i]*sc+0.5)-ir/2, ir, ir); } } void tempPlot(int gx, int gy, double sc, double offset, double mag) { int i,j,ir; double c; ir = (int)(0.5*sc+0.5); for (i=0; i1.0) c = 1.0; gOff.setColor(Color.getHSBColor((float)(0.66-0.66*c),0.8f,0.8f)); gOff.drawOval(gx+(int)(xx[i]*sc+0.5)-ir/2,gy+(int)(yy[i]*sc+0.5)-ir/2, ir, ir); } } /*-------------------------- set initial condition --------- */ void setInitialCondition() { int i,j,ix,iy; double s; t = 0.0; i = 0; /* water; density=1.0g/cc, specific heat=4200J/kgK */ for (ix=0; ix<36; ix++) { for (iy=0; iy<24; iy++) { kind[i] = 1; mass[i] = 1000.0/4.0; cp[i] = 4200.0; xx[i] = 4.0+1.0+0.3*(ix)+0.1+0.15*(iy%2); yy[i] = 3.0+3.2+0.3*(0.866*iy); vx[i] = 0.5*(Math.random()-0.5); vy[i] = 0.5*(Math.random()-0.5); ax[i] = 0.0; ay[i] = 0.0; hh[i] = hh0; i += 1; } } /* water tank; density=0.5g/cc, specific heat=1000J/kgK*/ for (ix=0; ix<50; ix++) { for (iy=0; iy<35; iy++) { if ( (ix<3||ix>46)&& iy<32 || iy>=32 ) { kind[i] = 0; mass[i] = 500.0/4.0; cp[i] = 1000.0; xx[i] = 4.0+0.866*rBond*ix; yy[i] = 3.0+rBond*iy+0.5*rBond*(ix%2); vx[i] = 0.0; vy[i] = 0.0; ax[i] = 0.0; ay[i] = 0.0; hh[i] = hh0; i += 1; } } } NNp = i; bonding(); dividingSection(); setDensity(); for (i=0; irb2) { bondUnreg(ii,jj); bondUnreg(jj,ii); q = 0; } break; } } return (q); } /* ----------------------------- timeEvolution -------------- */ void timeEvolution() { int i; if (resetSW==1) { setInitialCondition(); resetSW = 0; } if (started==1) { for (i=0; i0) { pressure[i] = 20.0*(Math.pow(density[i]/dens0,7.0)-1); /* gas pressure[i] = 8.31*density[i]*(energy[i]/(mass[i]*cp[i])); */ } else { pressure[i] = 0.5*density[i]; } } 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]; } } if (tPulse=Nsx) i1 = Nsx-1; j0 = (int)(Nsy*(yy[i]-rcc)/yMax); if (j0<0) j0 = 0; j1 = (int)(Nsy*(yy[i]+rcc)/yMax); if (j1>=Nsy) j1 = Nsy-1; for(ii=i0;ii<=i1;ii++) { for(jj=j0;jj<=j1;jj++) { for(iq=1;iq<=section[ii][jj][0];iq++) { j = section[ii][jj][iq]; r2=(xx[i]-xx[j])*(xx[i]-xx[j])+(yy[i]-yy[j])*(yy[i]-yy[j]); if (r20) { if (kind[j]>0 && kind[i]>0) { aj = pressure[j]/(density[j]*density[j]); vr = (xx[i]-xx[j])*(vx[i]-vx[j])+(yy[i]-yy[j])*(vy[i]-vy[j]); pij = 0; if (vr<0.0) { mu = 0.5*vr/(r2+0.001*0.5*0.5); pij = (-alpha*cv*mu+0.0*mu*mu)/((density[i]+density[j])/2.0); } b = mass[j]*(ai+aj+pij); gradW = dwwvdr(rij, (hh[i]+hh[j])/2.0); gradWx = gradW*(xx[i]-xx[j])/rij; gradWy = gradW*(yy[i]-yy[j])/rij; ax[i] += -b*gradWx; ay[i] += -b*gradWy; lapW = d2wwvdr2(rij, (hh[i]+hh[j])/2.0); power[i] += 0.5*b*((vx[i]-vx[j])*gradWx+(vy[i]-vy[j])*gradWy) + thermalDiffusivity*mass[j]/density[j]*(energy[j]-energy[i])*lapW; } else { a = force(rij,i,j)/mass[i]; ax[i] += a*(xx[i]-xx[j])/rij; ay[i] += a*(yy[i]-yy[j])/rij; } } } } } } } } double force(double r, int ii, int jj) { int i,j; double ret,rc,ra,ra1,ra2,ram,fa,f,r1,r3,kc; if (kind[ii]>=0 || kind[jj]>=0) { rc = hh0*1.2; ret = 0.0; if (rra2) { bondUnreg(i,j); bondUnreg(j,i); return ( 0.0 ); } f = 0.0; if (bondQ(i,j)==0) { if (r=ra2) { f = 0.0; bondUnreg(i,j); bondUnreg(j,i); } else if (ra1<=r && r xMax-rc) { r = xx[i]-(xMax-rc); ax[i] += -k*r*r; } if (yy[i] < rc) { r = rc-yy[i]; ay[i] += k*r*r; } if (yy[i] > yMax-rc) { r = yy[i]-(yMax-rc); ay[i] += -k*r*r; } } void setDensity() { int i,j,i0,i1,j0,j1,ii,jj,iq,ikind; double s,rij; double rcc,rcc2,r2; rcc = hh0*2.0; rcc2 = rcc*rcc; for (i=0; i=Nsx) i1 = Nsx-1; j0 = (int)(Nsy*(yy[i]-rcc)/yMax); if (j0<0) j0 = 0; j1 = (int)(Nsy*(yy[i]+rcc)/yMax); if (j1>=Nsy) j1 = Nsy-1; for(ii=i0;ii<=i1;ii++) { ikind = kind[i]; for(jj=j0;jj<=j1;jj++) { for(iq=1;iq<=section[ii][jj][0];iq++) { j = section[ii][jj][iq]; if (kind[j]==ikind) { r2=(xx[i]-xx[j])*(xx[i]-xx[j])+(yy[i]-yy[j])*(yy[i]-yy[j]); if (r2=Nsx) i = Nsx-1; j = (int)(Nsy*yy[ip]/yMax); if (j>=Nsy) j = Nsy-1; iq = section[i][j][0]+1; section[i][j][0] = iq; section[i][j][iq] = ip; } } int maxSection() { int i,j,m; m = 0; for(i=0;im) m = section[i][j][0]; } } return ( m ); } /*---------------------------- smoothed particle ---------*/ double kernel(double r, double h) { double a,q,ret; ret = 0.0; q = r/h; a = 10.0/(7.0*3.141592)/(h*h); if (q<1.0) { ret = a*(1.0-1.5*q*q+0.75*q*q*q); } else if (q<2.0) { ret = a*0.25*(2.0-q)*(2.0-q)*(2.0-q); } return ( ret ); } double dwwvdr(double r, double h) { double a,q,ret; ret = 0.0; q = r/h; a = 10.0/(7.0*3.141592)/(h*h*h); if (q<1.0) { ret = a*(-3.0*q+2.25*q*q); } else if (q<=2.0) { ret = -a*0.75*(2.0-q)*(2.0-q); } return ( ret ); } double d2wwvdr2(double r, double h) { double a,q,ret; ret = 0.0; q = r/h; a = 10.0/(7.0*3.141592)/(h*h*h*h); if (q<1.0) { ret = a*(-3.0+4.5*q); } else if (q<=2.0) { ret = a*0.75*(2.0-q); } return ( ret ); } /* ----------------------------- end of applet -------------- */ }